微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 如何动态调用泛型扩展方法?

我写了这个扩展方法
public static DataTable ToDataTable<T>(this IList<T> list)
{...}

如果在编译时使用已知类型调用它,它的效果很好:

DataTable tbl = new List<int>().ToDataTable();

但如果通用类型未知,如何调用呢?

object list = new List<int>();
...
tbl = Extension.ToDataTable((List<object>)list); // won't work

解决方法

发生这种情况是因为List< int>不是List< object> – List类型在其元素类型参数中不是协变的.不幸的是,您需要获取泛型方法的类型版本并使用反射调用它:
Type listItemType = typeof(int);   // cheating for simplicity - see below for real approach
MethodInfo openMethod = typeof(Extension).getmethod("ToDataTable",...);
MethodInfo typedMethod = openMethod.MakeGenericmethod(typeof(listItemType));
typedMethod.Invoke(null,new object[] { list });

另一种方法是创建一个接受IList而不是IList< T>的扩展方法的版本.列表< T> class实现了这个非泛型接口以及通用接口,因此您可以调用

public static DataTable WeakToDataTable(this IList list) { ... }

((IList)list).WeakToDataTable();

(实际上你可能会使用重载而不是其他名称 – 只需使用不同的名称调用不同的类型.)

更多信息:在反射解决方案中,我跳过了如何确定列表元素类型的问题.根据您想要的复杂程度,这可能有点棘手.如果您假设该对象将是List< T> (对于某些T)然后很容易:

Type listItemType = list.GetType().GetGenericArguments()[0];

如果你只是愿意承担IList< T>然后它有点难,因为你需要找到合适的接口并从中获取通用参数.而且你不能使用GetInterface(),因为你正在寻找一个通用接口的闭合构造实例.所以你必须浏览所有接口,寻找一个IList< T>的实例:

foreach (Type itf in list.GetType().GetInterfaces())
{
  if (itf.IsGenericType && itf.GetGenericTypeDeFinition == typeof(IList<>))  // note generic type deFinition Syntax
  {
    listItemType = itf.GetGenericArguments()[0];
  }
}

这适用于空列表,因为它取消了元数据,而不是列表内容.

原文地址:https://www.jb51.cc/csharp/100852.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐