恢复"丢失"类型参数

时间:2014-07-17 17:21:37

标签: c# generics

基本上,我的问题是:有没有办法恢复"通过向上转换为非通用基本类型而丢失的类型参数,例如Object。这是我的意思的一个例子:

考虑我从图书馆收到Object l,我知道lIList<T>,但我不知道T(但我知道它是一个引用类型,没有值类型)。但是,T的确切类型并不重要,因为我想要做的就是将l传递给通用方法:

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

但是,我不能这样做,因为我不知道要投射哪种类型l,即我想做以下事情:

doSomethingWithList((IList<>)l);

我想告诉编译器lIList,它应该调用该方法并将未知类型参数绑定到其参数T。但它并没有像这样工作。我有什么选择吗?我可以以某种方式传递一个我失去的对象吗?#34;泛型方法的类型参数?

2 个答案:

答案 0 :(得分:4)

你可以使用反射来做到这一点:

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以接受非通用列表...

答案 1 :(得分:2)

如果您知道这是安全的,最简单的解决方案是使用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 });
}