如何调用 System.Linq.Enumerable.Count<>在 IEnumerable 上使用反射?
我有一堆 IEnumerable 集合,其确切数量和类型经常发生变化(由于自动代码生成)。
它看起来像这样:
public class MyCollections {
public System.Collections.Generic.IEnumerable<SomeType> SomeTypeCollection;
public System.Collections.Generic.IEnumerable<OtherType> OtherTypeCollection;
...
在运行时,我想确定每种类型及其计数,而不必在每次代码生成后重写代码。所以我正在寻找一种使用反射的通用方法。我正在寻找的结果类似于:
MyType: 23
OtherType: 42
我的问题是我无法弄清楚如何正确调用 Count 方法。这是我到目前为止所拥有的:
// Handle to the Count method of System.Linq.Enumerable
MethodInfo countMethodInfo = typeof(System.Linq.Enumerable).GetMethod("Count", new Type[] { typeof(IEnumerable<>) });
PropertyInfo[] properties = typeof(MyCollections).GetProperties();
foreach (PropertyInfo property in properties)
{
Type propertyType = property.PropertyType;
if (propertyType.IsGenericType)
{
Type genericType = propertyType.GetGenericTypeDefinition();
if (genericType == typeof(IEnumerable<>))
{
// access the collection property
object collection = property.GetValue(someInstanceOfMyCollections, null);
// access the type of the generic collection
Type genericArgument = propertyType.GetGenericArguments()[0];
// make a generic method call for System.Linq.Enumerable.Count<> for the type of this collection
MethodInfo localCountMethodInfo = countMethodInfo.MakeGenericMethod(genericArgument);
// invoke Count method (this fails)
object count = localCountMethodInfo.Invoke(collection, null);
System.Diagnostics.Debug.WriteLine("{0}: {1}", genericArgument.Name, count);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您坚持采用困难的方式;p
更改:
(注意
obj
是我的MyCollections
实例):If you insist on doing it the hard way ;p
Changes:
Code (note
obj
is my instance ofMyCollections
):这将涉及一些
MakeGenericMethod
- 以及通常的大量反射。就我个人而言,在这种情况下,我很想通过放弃泛型来简化:即使通过反射获取,您也可以简单地转换为非泛型 IEnumerable 。
That is going to involve some
MakeGenericMethod
- and a lot of reflection generally. Personally, I would be tempted to just simplify by ditching the generics in this case:You can cast to the non-generic
IEnumerable
trivially, even if fetching via reflection.现在,问题已经得到解答,但我想向您展示“调用通用扩展方法”的精简版本(我认为相当简单),它可用于调用
Count
反射式:上面的方法有效,因为您不需要使用
IEnumerable
的泛型类型来调用Count,它是
Enumerable
的扩展,并采用IEnumerable
参数作为第一个参数(它是一个扩展),但您不需要指定它。请注意,从阅读您的问题来看,在我看来,您实际上应该为您的类型使用泛型,这会将类型安全性重新添加到您的项目中,并且仍然允许您使用 Count 或其他内容。毕竟,可以肯定的一件事是所有都是
Enumerable
,对吧?如果是这样,谁需要反思?By now, the question has been answered, but I'd like to present you a trimmed down — and I think, rather trivial version — of the "calling a generic extension method", which can be used to invoke
Count
reflectively:The above works, because you don't need to use the generic type of
IEnumerable<>
to be able to invokeCount
, which is an extension ofEnumerable
and takes an argument ofIEnumerable<T>
as first param (it's an extension), but you don't need to specify that.Note that, from the reading of your question, it seems to me that you should actually use generics for your types, which adds type safety back into your project and still allows you to use Count or whatever. After all, the one thing that's certain is that all are
Enumerable
, right? If so, who needs reflection?编辑:你说它是生成的,所以你不能只通过调用
Count()
来生成属性吗?Edit: you say it's generated though, so can you not just generate a properties with calls to
Count()
?