2011-01-06 14 views
8

मेरे पास ऑब्जेक्ट्स की एक सूची है, जिसमें से मैं संकलन-समय के प्रकार को नहीं जान सकता।जेनेरिक प्रकारों के प्रतिबिंब का उपयोग करके गणना संपत्ति कैसे प्राप्त करें

मुझे इन वस्तुओं में से किसी एक को पहचानने की आवश्यकता है जहां 'गणना' संपत्ति मौजूद है, और यदि यह करता है तो मूल्य प्राप्त करें।

इस कोड को सरल संग्रह प्रकार के लिए काम करता है:

PropertyInfo countProperty = objectValue.GetType().GetProperty("Count"); 
if (countProperty != null) 
{ 
    int count = (int)countProperty.GetValue(objectValue, null); 
} 

समस्या यह है कि इस तरह के IDictionary<TKey,TValue> के रूप में सामान्य प्रकार के लिए काम नहीं करता है, है। उन मामलों में, 'countProperty' मान शून्य के रूप में वापस किया जाता है, भले ही इंस्टेंट ऑब्जेक्ट में 'गणना' गुण मौजूद है।

मैं बस इतना करना चाहता हूं कि किसी भी संग्रह/शब्दकोश आधारित वस्तु की पहचान करें और इसका आकार ढूंढें, यदि उसके पास है।

संपादित करें: के रूप में अनुरोध किया है, यहाँ कि

private static void GetCacheCollectionValues(ref CacheItemInfo item, object cacheItemValue) 
{ 
    try 
     { 
     //look for a count property using reflection 
     PropertyInfo countProperty = cacheItemValue.GetType().GetProperty("Count"); 
     if (countProperty != null) 
     { 
      int count = (int)countProperty.GetValue(cacheItemValue, null); 
      item.Count = count; 
     } 
     else 
     { 
      //poke around for a 'values' property 
      PropertyInfo valuesProperty = cacheItemValue.GetType().GetProperty("Values"); 
      int valuesCount = -1; 
      if (valuesProperty != null) 
      { 
       object values = valuesProperty.GetValue(cacheItemValue, null); 
       if (values != null) 
       { 
        PropertyInfo valuesCountProperty = values.GetType().GetProperty("Count"); 
        if (countProperty != null) 
        { 
         valuesCount = (int)valuesCountProperty.GetValue(cacheItemValue, null); 
        } 
       } 
      } 
      if (valuesCount > -1) 
       item.Count = valuesCount; 
      else 
       item.Count = -1; 
     } 
    } 
    catch (Exception ex) 
    { 
     item.Count = -1; 
     item.Message = "Exception on 'Count':" + ex.Message; 
    } 
} 

काम नहीं करता है यह सरल संग्रह पर ठीक से काम करता है, लेकिन एक वर्ग मेरे पास है जो Dictionary<TKey,TValue> से ली गई है से बनाए गए एक वस्तु पर नहीं कोड की पूरी सूची है । यानी

CustomClass : 
    Dictionary<TKey,TValue> 

CacheItemInfo बस एक साधारण वर्ग है कि कैश मदों के लिए गुण होता है - यानी, कुंजी, गिनती, प्रकार, समाप्ति दिनांक

+0

(आईडीआई 'के संदर्भ में सोचने में मदद नहीं होगी, क्योंकि' गेट टाइप() 'हमेशा * कंक्रीट * प्रकार वापस लौटाएगा, जो कुछ भी हो सकता है, लेकिन संभवतः' डिक्शनरी ') –

+0

यहां कोड है यह खड़ा है - अभी भी काम नहीं करता है। –

+0

तो उत्तर प्रतिबिंब को अनदेखा करना था और केवल इंटरफेस पर डालना था - नीचे सही उत्तर देखें। –

उत्तर

11

पहली बात यह है के रूप में यह एक है आप, प्रयास करना चाहिए ICollection पर कास्ट करना है बहुत सस्ते .Count:

ICollection col = objectValue as ICollection; 
if(col != null) return col.Count; 

शब्दकोश हालांकि काम करना चाहिए के लिए Count - मैं Dictionary<,> के साथ इस परीक्षण किया है और यह ठीक काम करता है - लेकिन ध्यान दें कि कुछ को लागू करता है, भले हीयह स्पष्ट इंटरफेस कार्यान्वयन का उपयोग इंटरफेस को पूरा करने के जबकि नहीं एक public int Count {get;} होने सकता है -, ठोस प्रकार (GetType() के माध्यम से लौटे) नहीं करता सार्वजनिक एपीआई पर एक .Count करना होगा। जैसे मैं कहता हूं: यह Dictionary<,> के लिए काम करता है - लेकिन हर प्रकार के लिए जरूरी नहीं है।

एक अंतिम खाई प्रयास के रूप में अगर सब कुछ कुछ विफल: Dictionary<,> प्रश्न टिप्पणी में उठाया गौर करने

IEnumerable enumerable = objectValue as IEnumerable; 
if(enumerable != null) 
{ 
    int count = 0; 
    foreach(object val in enumerable) count++; 
    return count; 
} 

संपादित करें:

using System; 
using System.Collections; 
using System.Collections.Generic; 
public class CustomClass : Dictionary<int, int> { } 
public class CacheItemInfo 
{ 
    public int Count { get; set; } 
    public string Message { get; set; } 
} 
class Program { 
    public static void Main() { 
     var cii = new CacheItemInfo(); 
     var data = new CustomClass { { 1, 1 }, { 2, 2 }, { 3, 3 } }; 
     GetCacheCollectionValues(ref cii, data); 
     Console.WriteLine(cii.Count); // expect 3 
    } 
    private static void GetCacheCollectionValues(ref CacheItemInfo item, object cacheItemValue) 
    { 
     try 
     { 
      ICollection col; 
      IEnumerable enumerable; 
      if (cacheItemValue == null) 
      { 
       item.Count = -1; 
      } 
      else if ((col = cacheItemValue as ICollection) != null) 
      { 
       item.Count = col.Count; 
      } 
      else if ((enumerable = cacheItemValue as IEnumerable) != null) 
      { 
       int count = 0; 
       foreach (object val in enumerable) count++; 
       item.Count = count; 
      } 
      else 
      { 
       item.Count = -1; 
      } 
     } 
     catch (Exception ex) 
     { 
      item.Count = -1; 
      item.Message = "Exception on 'Count':" + ex.Message; 
     } 
    } 
} 
+0

मार्क - आपके योगदान के लिए धन्यवाद।मैंने पाया है कि मैंने अपने मूल प्रश्न से महत्वपूर्ण जानकारी छोड़ी है - कक्षाओं में से एक जिसे मैं देख रहा हूं शब्दकोश से प्राप्त होता है और यह उन लोगों में से एक है जो काम नहीं करते हैं। गणना()। आप IDictionary <,> के साथ परीक्षण का जिक्र करते हैं - क्या आप उस कोड को पोस्ट कर सकते हैं जिसका आपने उपयोग किया था? –

+0

@ ब्रूस - मैंने 'डिक्शनरी <,>' के साथ परीक्षण किया - कंक्रीट प्रकार (इंटरफेस सीधे 'गेटटाइप()' के साथ अप्रासंगिक हैं - और इसे अभी भी इसके सबक्लास के साथ काम करना चाहिए। क्या आप कोड दिखा सकते हैं जो * काम नहीं करता है? मैं बस एक शब्दकोश में पास हो गया। –

+0

मार्क - देरी के बारे में खेद है कि किसी भी तरह से जहाज भेजना पड़ा। मैंने पूरा कोड पोस्ट किया है जिसका उपयोग मैं कर रहा हूं, यह अभी भी शब्दकोश वस्तुओं के साथ काम नहीं करता है। –

1

कैसे अपनी पहली जांच के बाद इस जोड़ने के बारे में (! untested!) ...

foreach (Type interfaceType in objectValue.GetType().GetInterfaces()) 
{ 
    countProperty = interfaceType.GetProperty("Count"); 
    //etc. 
} 
संबंधित मुद्दे

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