2009-06-25 10 views
88

मैं एक प्रतिबिंब परियोजना पर काम कर रहा हूं, और अब मैं अटक गया हूं। यदि मेरे पास "myclass" का कोई ऑब्जेक्ट है जो सूची रख सकता है, तो क्या कोई यह जानता है कि संपत्ति myclass.SomList खाली है, तो नीचे दिए गए कोड में टाइप कैसे प्राप्त करें?सी # सामान्य सूची <T> टी के प्रकार कैसे प्राप्त करें?

List<myclass> myList = dataGenerator.getMyClasses(); 
lbxObjects.ItemsSource = myList; 
lbxObjects.SelectionChanged += lbxObjects_SelectionChanged; 

private void lbxObjects_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      Reflect(); 
     } 
Private void Reflect() 
{ 
foreach (PropertyInfo pi in lbxObjects.SelectedItem.GetType().GetProperties()) 
{ 
     switch (pi.PropertyType.Name.ToLower()) 
     { 
     case "list`1": 
      {   
      // This works if the List<T> contains one or more elements. 
      Type tTemp = GetGenericType(pi.GetValue(lbxObjects.SelectedItem, null)); 

      // but how is it possible to get the Type if the value is null? 
      // I need to be able to create a new object of the type the generic list expect. 
      // Type type = pi.getType?? // how to get the Type of the class inside List<T>? 
      break; 
      } 
     } 
} 
} 
private Type GetGenericType(object obj) 
     { 
      if (obj != null) 
      { 
       Type t = obj.GetType(); 
       if (t.IsGenericType) 
       { 
        Type[] at = t.GetGenericArguments(); 
        t = at.First<Type>(); 
       } return t; 
      } 
      else 
      { 
       return null; 
      } 
     } 

उत्तर

174
Type type = pi.PropertyType.PropertyType; 
if(type.IsGenericType && type.GetGenericTypeDefinition() 
     == typeof(List<>)) 
{ 
    Type itemType = type.GetGenericArguments()[0]; // use this... 
} 

आम तौर पर, किसी भी IList<T> समर्थन करने के लिए, आप इंटरफेस जांच करने की आवश्यकता:

foreach (Type interfaceType in type.GetInterfaces()) 
{ 
    if (interfaceType.IsGenericType && 
     interfaceType.GetGenericTypeDefinition() 
     == typeof(IList<>)) 
    { 
     Type itemType = type.GetGenericArguments()[0]; 
     // do something... 
     break; 
    } 
} 
+8

यह प्रकार itemtype = interfaceType.GetGenericArguments() नहीं होना चाहिए [0]; – Muxa

+0

Amusingly, दूसरा उदाहरण 'IList ' कहता है, के साथ विफल रहता है। नीचे ठीक करें http://stackoverflow.com/a/13608408/284795 –

+0

मुझे पता है कि उत्तर बहुत पुराना है, लेकिन मैं निम्नलिखित को समझने की कोशिश करता हूं: 'GetGenericArguments() [0];' 0 क्यों है? क्या टाइप [] में केवल हमेशा एक आइटम है? – Ismoh

7

मार्क के जवाब दृष्टिकोण मैं इस के लिए उपयोग है, लेकिन सादगी के लिए (और एक दोस्ताना एपीआई?) आप संग्रह बेस क्लास में एक संपत्ति को परिभाषित कर सकते हैं यदि आपके पास ऐसा कोई है:

public abstract class CollectionBase<T> : IList<T> 
{ 
    ... 

    public Type ElementType 
    { 
     get 
     { 
     return typeof(T); 
     } 
    } 
} 

मुझे यह दृष्टिकोण उपयोगी पाया गया है, और जेनेरिक के लिए किसी भी नए आने वालों के लिए समझना आसान है।

+0

मैं इस दृष्टिकोण का उपयोग करना चाहता था लेकिन फिर मुझे एहसास हुआ कि मुझे तत्व प्रकार निर्धारित करने के लिए सूची उदाहरण होना होगा, जो कि मेरे पास हमेशा नहीं होगा। – Muxa

+1

आप संपत्ति को स्थिर बना सकते हैं।जैसा "सार्वजनिक स्थिर प्रकार elementType" ... तो आप के रूप में यह पर मिलता है "var टी = CollectionBase .ElementType," ... आपको एक आवृत्ति चर – Nabheet

+0

सत्य की आवश्यकता नहीं होगी। स्टेटिक आपको किसी मौजूदा ऑब्जेक्ट के बिना कक्षा के साथ काम करने की अनुमति देता है। मुझे इस दृष्टिकोण को काम करने में आसान लगता है। बेशक, आप अपने वस्तुओं में अतिरिक्त जानकारी स्टोर करने के लिए लेकिन कम से कम आप अपने आप को मंजूरी दे दी है जवाब में यह झरना-कॉल से अतिरिक्त जरूरत है। (Int32 भी मार्क्स के साथ मैं मिल) – rbaleksandar

4

एक वस्तु जो मैं IList<> किसी तरह का होने की संदेह को देखते हुए, मैं क्या यह एक IList<> है की कैसे तय कर सकते हैं?

यहां एक विश्वसनीय समाधान है। लंबाई के लिए मेरी माफ़ी - सी # की आत्मनिरीक्षण एपीआई इस आश्चर्यजनक रूप से मुश्किल बनाती है।

/// <summary> 
/// Test if a type implements IList of T, and if so, determine T. 
/// </summary> 
public static bool TryListOfWhat(Type type, out Type innerType) 
{ 
    Contract.Requires(type != null); 

    var interfaceTest = new Func<Type, Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>) ? i.GetGenericArguments().Single() : null); 

    innerType = interfaceTest(type); 
    if (innerType != null) 
    { 
     return true; 
    } 

    foreach (var i in type.GetInterfaces()) 
    { 
     innerType = interfaceTest(i); 
     if (innerType != null) 
     { 
      return true; 
     } 
    } 

    return false; 
} 

उदाहरण उपयोग:

object value = new ObservableCollection<int>(); 
Type innerType; 
TryListOfWhat(value.GetType(), out innerType).Dump(); 
innerType.Dump(); 

रिटर्न

True 
typeof(Int32) 
+0

मैं मार्क्स पद्धति के रूप में किसी भी अन्य परिणाम नहीं दिख रहा है – Offler

17

एक वस्तु जो मैं IList<> किसी तरह का होने के लिए संदेह है, मैं कैसे निर्धारित कर सकते हैं क्या की यह एक IList<> है को देखते हुए ?

यहां गड़बड़ समाधान है। यह मानता है कि आपके पास परीक्षण करने के लिए वास्तविक वस्तु है (Type के बजाय)।

public static Type ListOfWhat(Object list) 
{ 
    return ListOfWhat2((dynamic)list); 
} 

private static Type ListOfWhat2<T>(IList<T> list) 
{ 
    return typeof(T); 
} 

उदाहरण उपयोग:

object value = new ObservableCollection<DateTime>(); 
ListOfWhat(value).Dump(); 

प्रिंटों

typeof(DateTime) 
+0

-1: क्यों 'IList ' 'IEnumerable ' के बजाय? क्यों 'गतिशील'? –

+0

मैं ओपी के सवाल का गलत किया? विस्तार अस्पष्ट था, इसलिए मैंने शीर्षक में सवाल का जवाब दिया। –

+3

आप महोदय, एक जादूगर हैं! मैं एक सामान्य डेटा संरचना (जो एकवचन प्रकार और सूचियों से निपट सकता है) के साथ एक गतिशील पार्सर के साथ एक समस्या को हल करने की कोशिश कर रहा है और * यह * मुझे सही रास्ते पर मिला। –

संबंधित मुद्दे