2012-10-04 16 views
8

संभव डुप्लिकेट का आधार प्रकार प्राप्त करने के लिए कैसे:
getting type T from IEnumerable<T>एक IEnumerable

मैं IEnumerable

public IEnumerable PossibleValues { get; set; }

मैं कैसे पता लगा सकते हैं की एक संपत्ति प्रकार है मूल प्रकार जिसे इसे इंस्टाल किया गया था?

उदाहरण के लिए, अगर यह इस तरह बनाया गया था:

PossibleValues = new int?[] { 1, 2 } 

मैं उस प्रकार जानना चाहता हूँ 'int' है।

+5

@Arran, कि जेनेरिक वर्जन –

+0

@Arran को दर्शाता है:। जरूरी नहीं है, अगर वहाँ है पहलू में कोई महत्व है कि ओपी 'Nullable ' की एक सरणी दिखाता है, लेकिन 'int' को पुनर्प्राप्त करना चाहता है। –

+0

आह सच है, मुझे अनदेखा करें :) – Arran

उत्तर

3

आप यह कर सकते हैं अगर आप PossibleValues ​​के प्रकार हैं:

var type = PossibleValues.GetType().ToString(); // "System.Nullable`1[System.Int32][]" 

या आप यह कर सकते हैं यदि आप किसी आइटम के प्रकार (PossibleValues ​​में निहित संभालने सरणी वास्तव में मूल्य हैं में वर्णित के रूप चाहते हैं कि आपके प्रश्न):

var type = PossibleValues.Cast<object>().First().GetType().ToString(); // "System.Int32" 



संपादित

यदि यह एक संभावना है कि सरणी कोई आइटम नहीं हो सकती है, तो आप निश्चित रूप से, कुछ अशक्त जाँच करना होगा:

var firstItem = PossibleValues.Cast<object>().FirstOrDefault(o => o != null); 
var type = string.Empty; 
if (firstItem != null) 
{ 
    type = firstItem.GetType().ToString(); 
} 
+0

आप यह जांचना चाहेंगे कि अनुक्रम में पहले को खींचने से पहले मूल्य हैं। – Servy

+1

यही कारण है कि मैंने कहा "सरणी मानते हैं कि वास्तव में मूल्य हैं"। – bugged87

+0

यदि उसके पास मूल्य नहीं हैं तो शायद यह एक प्रकार (जो अभी भी काम नहीं कर रहा है) के साथ नहीं आना चाहिए, लेकिन अपवाद फेंकना नहीं चाहिए। – Servy

8
Type GetBaseTypeOfEnumerable(IEnumerable enumerable) 
{ 
    if (enumerable == null) 
    { 
     //you'll have to decide what to do in this case 
    } 

    var genericEnumerableInterface = enumerable 
     .GetType() 
     .GetInterfaces() 
     .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)); 

    if (genericEnumerableInterface == null) 
    { 
     //If we're in this block, the type implements IEnumerable, but not IEnumerable<T>; 
     //you'll have to decide what to do here. 

     //Justin Harvey's (now deleted) answer suggested enumerating the 
     //enumerable and examining the type of its elements; this 
     //is a good idea, but keep in mind that you might have a 
     //mixed collection. 
    } 

    var elementType = genericEnumerableInterface.GetGenericArguments()[0]; 
    return elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(Nullable<>) 
     ? elementType.GetGenericArguments()[0] 
     : elementType; 
} 

यह उदाहरण कुछ सीमाएँ, जो आपके आवेदन में आपको चिंता हो सकती है या नहीं। यह उस मामले को संभाल नहीं करता है जहां प्रकार IEnumerable लागू करता है लेकिन IEnumerable<T> नहीं। यदि प्रकार IEnumerable<T> एक से अधिक बार लागू करता है, तो यह मनमाने ढंग से एक कार्यान्वयन को चुनता है।

+0

धन्यवाद, जब मेरे पास पर्याप्त प्रतिष्ठा है तो मैं आपका उत्तर देता हूं। –

+0

मैं एक और जवाब का उपयोग कर रहा हूं, लेकिन सीखना अच्छा था। –

+0

@RooniZacaron मैंने आपके प्रश्न को उखाड़ फेंक दिया है, इसलिए अब आपके पास उत्तर देने के लिए पर्याप्त प्रतिष्ठा है (बधाई हो)। आप जिस जवाब का उपयोग कर रहे हैं उसे स्वीकार करना न भूलें! – phoog

2

दो मौजूदा दृष्टिकोण यह देखने के लिए हैं कि ऑब्जेक्ट IEnumerable<T> लागू करता है या सेट में पहले आइटम के प्रकार की जांच करने के लिए। पहला वास्तव में IEnumerable<T> को लागू करने वाले ऑब्जेक्ट पर निर्भर करता है, और दूसरा केवल तभी काम करता है जब अनुक्रम में सभी आइटम समान व्युत्पन्न प्रकार के होते हैं।

एक दिलचस्प सवाल जो आप पूछ सकते हैं वह है कि सभी वस्तुओं में आम प्रकार क्या हैं, या सभी वस्तुओं के बीच सबसे संकीर्ण प्रकार क्या है।

हम एक साधारण सहायक विधि के साथ शुरू करेंगे। एक प्रकार को देखते हुए यह उस प्रकार का अनुक्रम और उसके सभी मूल प्रकारों को वापस कर देगा।

public static IEnumerable<Type> getBaseTypes(Type type) 
{ 
    yield return type; 

    Type baseType = type.BaseType; 
    while (baseType != null) 
    { 
     yield return baseType; 
     baseType = baseType.BaseType; 
    } 
} 

अगला हम पहले, सबसे व्युत्पन्न प्रकार के सभी खोजने तो क्रम में प्रत्येक प्रकार के लिए आधार प्रकार के सभी हो रही द्वारा एक दृश्य के लिए आम प्रकार के सभी प्राप्त करने के लिए एक विधि है, और अंत में intersect का उपयोग कर केवल उन वस्तुओं वे सभी आम में है पाने के लिए:

public static IEnumerable<Type> getCommonTypes(IEnumerable source) 
{ 
    HashSet<Type> types = new HashSet<Type>(); 
    foreach (object item in source) 
    { 
     types.Add(item.GetType()); 
    } 

    return types.Select(t => getBaseTypes(t)) 
     .Aggregate((a, b) => a.Intersect(b)); 
} 

ध्यान दें कि पहली विधि में प्रकार के आदेश देने की सबसे कम से कम प्राप्त होने वाले ली गई है से, और Intersect आदेश रखता है, ताकि परिणामस्वरूप अनुक्रम हो जाएगा सबसे व्युत्पन्न से कम से कम व्युत्पन्न से क्रम में। यदि आप इन सभी प्रकारों के लिए सबसे संकीर्ण प्रकार सामान्य खोजना चाहते हैं तो आप इस विधि के परिणामस्वरूप First का उपयोग कर सकते हैं। (ध्यान दें कि जब सब कुछ object से निकला है वहाँ हमेशा हो जाएगा कम से कम एक प्रकार यहाँ लौटे जब तक कि वहाँ मूल IEnumerable में कोई आइटम नहीं हैं