How to get counter from ICollection <T> with unknown T
Here is my code:
//TODO: Look for a way of handling ICollection<T> if (value is ICollection) { return CreateResult(validationContext, ((ICollection)value).Count); } if (value is IEnumerable) { var enumerator = ((IEnumerable)value).GetEnumerator(); try { var count = 0; while (enumerator.MoveNext()) count++; return CreateResult(validationContext, count); } finally { if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose(); } }
Is there a good way to get Count
from ICollection<T>
without resorting to iterating over the collection?
A reflection would be correct, but keep in mind that most Collections in FCL inherit from both ICollection<T>
and ICollection
So code like this works:
var collection = new List<int>(); Console.WriteLine(collection is ICollection<MyClass>); Console.WriteLine(collection is ICollection);
True is output for both. This works for most, if not all, collections in FCL. If you needed to work with custom collections or collections that do not implement ICollection, then reflection is the only way.
Sidenote: arrays also implicitly implement ICollection, IList, and IEnumerable (the CLR actually generates an array that inherits from common versions of these classes in addition to non-generic at runtime), so your code above will work with arrays as well.
You will need to use reflection:
var genCollType = value.GetType() .GetInterfaces() .FirstOrDefault (i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollection<>)); if (genCollType != null) { int count = (int)genCollType.GetProperty("Count") .GetValue(value, null); return CreateResult(validationContext, count); }
Both ICollection and IEnumerable Interfaces have the Count property. Common versions as well.
if (value is ICollection) { return CreateResult(validationContext, ((ICollection)value).Count); } if (value is IEnumerable) { return CreateResult(validationContext, ((IEnumerable)value).Count); }
MSDN documentation for ICollection http://msdn.microsoft.com/en-us/library/system.collections.icollection.aspx
MSDN documentation for IEnumerable http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx