这是因为一个List<int>
不是List<object>
- 列表类型并不将其元件类型参数协变。不幸的是,你需要得到泛型方法的类型化版本,并使用反射调用它:
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>
。该List<T>
类实现此非通用接口以及通用接口,这样你就能拨打:
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];
}
}
这将为空列表的工作,因为它熄灭的元数据,而不是列表内容。
为什么你投到'列表
因为他在编译时不知道他有什么类型的列表:他不知道它是'List'。他试图通过将其转换为基类来解决该问题(正如你正确地指出的那样,尽管'int'与'object'兼容,那么'List '与列表