我如何从ICollection有一个未知的T
本文关键字:有一个 未知 ICollection | 更新日期: 2023-09-27 18:16:16
我的代码如下:
//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>
中取出?
如果没有ICollection<T>
的封闭类型,您将不得不求助于反射来调用Count属性。
if (typeof(ICollection<>) == value.GenericTypeDefinition()) {
var countProp = value.GetType().GetProperty("Count");
var count = (int)countProp.GetValue(value, null);
}
你必须使用反射:
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);
}
反射将是一种方式,但请记住,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实际上生成了一个数组,除了在运行时继承了这些类的泛型版本之外,还继承了非泛型版本),所以你上面的代码也可以处理数组。
ICollection和IEnumerable接口都有Count的属性。通用版本也是如此。
if (value is ICollection)
{
return CreateResult(validationContext, ((ICollection)value).Count);
}
if (value is IEnumerable)
{
return CreateResult(validationContext, ((IEnumerable)value).Count);
}
iccollection的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