I have a list of objects, of which I cannot know the type of at compile-time.
I need to identify any of these objects where a ‘Count’ property exists, and get the value if it does.
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 doesn’t work for generic types, such as IDictionary<TKey,TValue>. In those cases, the ‘countProperty’ value is returned as null, even though a ‘Count’ property exists in the instanced object.
All I want to do is identify any collection/dictionary based object and find the size of it, if it has one.
Edit: as requested, here’s the entire listing 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 OK on simple collections, but not on an object created from a class I have which is derived from Dictionary<TKey,TValue>. Ie
CustomClass :
Dictionary<TKey,TValue>
CacheItemInfo is just a simple class that contains properties for cache items – ie, key, count, type, expiration datetime
The first thing you should try is casting to
ICollection, as this has a very cheap.Count:The
Countfor dictionary should work though – I’ve tested this withDictionary<,>and it works fine – but note that even if something implementsIDictionary<,>, the concrete type (returned viaGetType()) doesn’t have to have a.Counton the public API – it could use explicit interface implementation to satisfy the interface while not having apublic int Count {get;}. Like I say: it works forDictionary<,>– but not necessarily for every type.As a last ditch effort if everything else fails:
Edit to look into the
Dictionary<,>question raised in comments: