如何动态调用通用扩展方法?
我写了这个扩展方法:
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
I wrote this extension method:
public static DataTable ToDataTable<T>(this IList<T> list)
{...}
It works well if called with a type known at compile time:
DataTable tbl = new List<int>().ToDataTable();
But how to call it if the generic type isn't known?
object list = new List<int>();
...
tbl = Extension.ToDataTable((List<object>)list); // won't work
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
发生这种情况是因为
List
不是List
另一种方法可能是创建一个接受
IList
而不是IList的扩展方法版本。
。List
类实现了这个非泛型接口以及泛型接口,因此您将能够调用:(实际上您可能会使用重载而不是不同的名称 - - 只是使用不同的名称来调用不同的类型。)
更多信息:在反射解决方案中,我跳过了如何确定列表元素类型的问题。这可能有点棘手,具体取决于您想要达到的复杂程度。如果您假设该对象将是
List
(对于某些 T),那么很简单:如果您只愿意假设
IList
那么这就有点困难了,因为您需要找到适当的接口并从中获取通用参数。并且您不能使用 GetInterface(),因为您正在寻找通用接口的封闭构造实例。因此,您必须仔细检查所有接口,寻找IList
的实例:这适用于空列表,因为它会超出元数据,而不是列表内容。
This occurs because a
List<int>
is not aList<object>
-- the List type is not covariant in its element type parameter. Unfortunately you would need to get a typed version of the generic method and call it using reflection:An alternative may be to create a version of your extension method that accepts
IList
rather thanIList<T>
. TheList<T>
class implements this non-generic interface as well as the generic interface, so you will be able to call:(In reality you'd probably use an overload rather than a different name -- just using a different name to call out the different types.)
More info: In the reflection solution, I skipped over the problem of how to determine the list element type. This can be a bit tricky depending on how sophisticated you want to get. If you're assuming that the object will be a
List<T>
(for some T) then it's easy:If you're only willing to assume
IList<T>
then it's a bit harder, because you need to locate the appropriate interface and get the generic argument from that. And you can't use GetInterface() because you're looking for a closed constructed instance of a generic interface. So you have to grovel through all the interfaces looking for one which is an instance ofIList<T>
:This will work for empty lists because it goes off the metadata, not the list content.
在使用
IList
接口时遇到问题后,我使用IList
接口解决了这个问题,例如 itowlson 提议。由于 _T 方法,它有点难看,但效果很好:After having trouble to get it working with the
IList<T>
interface I solved it using theIList
interface like itowlson proposed. It's a little bit ugly because of the _T method but it works well: