到目前为止,这是我的代码:
//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();
}
}
有没有一种很好的方法可以让Count
从ICollection<T>
中取出而不需要迭代收集?
答案 0 :(得分:5)
如果没有封闭类型的ICollection<T>
,则必须使用反射来调用Count属性。
if (typeof(ICollection<>) == value.GenericTypeDefinition()) {
var countProp = value.GetType().GetProperty("Count");
var count = (int)countProp.GetValue(value, null);
}
答案 1 :(得分:4)
你必须使用反射:
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);
}
答案 2 :(得分:1)
反思将是要走的路,但请记住,FCL中的大多数集合都继承自ICollection<T>
和ICollection
所以这样的代码可以工作:
var collection = new List<int>();
Console.WriteLine(collection is ICollection<MyClass>);
Console.WriteLine(collection is ICollection);
两者都输出True。这适用于FCL中的大多数(如果不是全部)集合。如果您需要它来处理自定义集合或未实现ICollection的集合,那么反射是唯一的方法。
旁注:数组也隐式实现了ICollection,IList和IEnumerable(CLR实际上生成了一个数组,除了运行时的非泛型之外,还继承了这些类的泛型版本),因此上面的代码可以用于数组好。
答案 3 :(得分:-1)
ICollection和IEnumerable接口都具有Count的属性。通用版本。
if (value is ICollection)
{
return CreateResult(validationContext, ((ICollection)value).Count);
}
if (value is IEnumerable)
{
return CreateResult(validationContext, ((IEnumerable)value).Count);
}
ICollection的MSDN文档 http://msdn.microsoft.com/en-us/library/system.collections.icollection.aspx
IEnumerable的MSDN文档 http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx