c# - जेनेरिक क्लास या विधि के सदस्य से टी का प्रकार कैसे प्राप्त करें?




.net generics (11)

मान लें कि मेरे पास कक्षा या विधि में एक सामान्य सदस्य है, इसलिए:

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

जब मैं कक्षा को तुरंत चालू करता MyTypeObject1 , तो T MyTypeObject1 बन जाता है, इसलिए कक्षा में एक सामान्य सूची संपत्ति होती है: List<MyTypeObject1> । गैर-जेनेरिक वर्ग में एक सामान्य विधि पर भी लागू होता है:

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

मैं जानना चाहता हूं कि मेरी कक्षा की सूची में किस प्रकार की वस्तुएं शामिल हैं। तो Bar या स्थानीय परिवर्तनीय baz नामक सूची संपत्ति में किस प्रकार का T ?

मैं Bar[0].GetType() नहीं कर सकता Bar[0].GetType() , क्योंकि सूची में शून्य तत्व हो सकते हैं। मैं यह कैसे कर सकता हूं?


(ध्यान दें: मुझे लगता है कि आप जो जानते हैं वह object या IList या समान है, और यह कि सूची रनटाइम पर किसी भी प्रकार का हो सकती है)

यदि आप जानते हैं कि यह एक List<T> , तो:

Type type = abc.GetType().GetGenericArguments()[0];

सूचकांक को देखने का एक और विकल्प है:

Type type = abc.GetType().GetProperty("Item").PropertyType;

नए टाइपइन्फो का उपयोग करना:

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

3 डीग्राबर के समाधान का उपयोग करना:

public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return default(T);
}

//and now 

var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();

आप किसी भी संग्रह प्रकार से "टी" का प्रकार प्राप्त कर सकते हैं जो निम्नलिखित के साथ IENumerable <T> लागू करता है:

public static Type GetCollectionItemType(Type collectionType)
{
    var types = collectionType.GetInterfaces()
        .Where(x => x.IsGenericType 
            && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        .ToArray();
    // Only support collections that implement IEnumerable<T> once.
    return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}

ध्यान दें कि यह संग्रह प्रकारों का समर्थन नहीं करता है जो IENumerable <T> को दो बार लागू करते हैं, उदाहरण के लिए

public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }

मुझे लगता है कि यदि आप इसका समर्थन करने की आवश्यकता है तो आप प्रकारों की एक सरणी वापस कर सकते हैं ...

साथ ही, यदि आप इसे बहुत कुछ कर रहे हैं (उदाहरण के लिए लूप में) तो आप परिणाम प्रति संग्रह प्रकार को कैश करना चाहेंगे।


इस पर विचार करें: मैं 20 टाइप की गई सूची को उसी तरह निर्यात करने के लिए इसका उपयोग करता हूं:

private void Generate<T>()
{
    T item = (T)Activator.CreateInstance(typeof(T));

    ((T)item as DemomigrItemList).Initialize();

    Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
    if (type == null) return;
    if (type != typeof(account)) //account is listitem in List<account>
    {
        ((T)item as DemomigrItemList).CreateCSV(type);
    }
}

प्रकार:

type = list.AsEnumerable().SingleOrDefault().GetType();

प्रयत्न

list.GetType().GetGenericArguments()

मैंने इस तरह से इसे किया

internal static Type GetElementType(this Type type)
{
        //use type.GenericTypeArguments if exist 
        if (type.GenericTypeArguments.Any())
         return type.GenericTypeArguments.First();

         return type.GetRuntimeProperty("Item").PropertyType);
}

फिर इसे इस तरह बुलाओ

var item = Activator.CreateInstance(iListType.GetElementType());

या

var item = Activator.CreateInstance(Bar.GetType().GetElementType());

यदि आप किसी संपत्ति के अंतर्निहित प्रकार को जानना चाहते हैं, तो इसे आजमाएं:

propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]

यह मेरे लिए काम है। जहां MyList कुछ अनजान सूची है।

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

GetGenericArgument() विधि को आपके उदाहरण के बेस प्रकार पर सेट करना होगा (जिसका वर्ग एक सामान्य वर्ग myClass<T> )। अन्यथा, यह एक प्रकार देता है [0]

उदाहरण:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

public string ListType<T>(T value){
    var valueType = value.GetType().GenericTypeArguments[0].FullName;
    return value;
}

आप जेनेरिक सूची के पुन: प्रकार के प्रकार के लिए इसका उपयोग कर सकते हैं।





generics