找回“丢失的”类型参数

本文关键字:丢失的 类型参数 找回 | 更新日期: 2023-09-27 18:13:26

基本上,我的问题是:是否有某种方法可以"恢复"由于上转换为非泛型基类型而丢失的类型参数,例如Object。下面是我的意思的一个例子:

考虑我从库中收到了Object l,我知道lIList<T>,但我不知道T(但我知道它是引用类型,没有值类型)。然而,T的确切类型并不重要,因为我想做的只是将l传递给泛型方法:

void doSomethingWithList<T>(IList<T> l){ ... }

但是,我不能这样做,因为我不知道将l转换为哪种类型,即,我想做以下操作:

doSomethingWithList((IList<>)l);

我想告诉编译器lIList,它应该调用该方法并将未知类型参数绑定到它的参数T。但它不是这样工作的。我还有别的选择吗?我是否可以通过某种方式将我"丢失"类型参数的对象传递给泛型方法?

找回“丢失的”类型参数

您可以使用反射:

var interfaceType = l.GetType().GetInterface("System.Collections.Generic.IList`1");
var itemType = interfaceType.GetGenericArguments()[0]; // This is your T
var method = this.GetType().GetMethod("doSomethingWithList").MakeGenericMethod(itemType);
method.Invoke(this, new object[] { l });

但如果可以,最好更改doSomethingWithList以接受非通用列表…

如果你知道它是安全的,最简单的解决方案是使用dynamic:

doSomethingWithList((dynamic)l);

否则,你可以检查l实现IList<T>的一些T,并通过反射调用方法:

var listType = l.GetType().GetInterfaces().FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
if (listType != null)
{
    Type elementType = listType.GetGenericArguments()[0];
    var method = this.GetType().GetMethod("doSomethingWithList").MakeGenericMethod(elementType);
    method.Invoke(this, new object[] { l });
}