How to get Count property using reflection for generic types

I have a list of objects from which I cannot know the type at compile time.

I need to identify any of these objects where the Count property exists and get the value, if any.

This code works for simple Collection types:

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

The problem is that this does not work for generic types like IDictionary<TKey,TValue> . In these cases, the value "countProperty" is returned as null, although the property "Count" exists in the instanced object.

All I want to do is identify any object based on the collection / dictionary and find its size, if any.

Edit: on request here is a complete list of code that doesn't work

 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; } } 

This works fine in simple collections, but not on an object created from class I, which is derived from Dictionary<TKey,TValue> . Those.

 CustomClass : Dictionary<TKey,TValue> 

CacheItemInfo is just a class that contains properties for cache elements, i.e. key, counter, type, expiration date

+8
reflection c #
source share
2 answers

The first thing you should try is to click on ICollection , as it is very cheap .Count :

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

The Count dictionary for the dictionary should work, though - I tested it with Dictionary<,> , and it works fine, but note that even if something implements IDictionary<,> , the specific type (returned via GetType() ) doesn 't must have .Count in the public API - it can use an explicit implementation of the interface to satisfy the interface, while it does not have a public int Count {get;} . As I say: it works for Dictionary<,> - but not necessarily for each type.

As a final groove effort, if all else fails:

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

Edit to view the Dictionary<,> question posed in the comments:

 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; } } } 
+11
source share

How to add this after the first check (! Untested!) ...

 foreach (Type interfaceType in objectValue.GetType().GetInterfaces()) { countProperty = interfaceType.GetProperty("Count"); //etc. } 
+1
source share

Source: https://habr.com/ru/post/650736/


All Articles