输入参数 - 从类型T获取具体类型:IMyInterface

时间:2011-07-22 15:49:33

标签: c#-4.0 interface downcast type-parameter

假设我有List<IMyInterface> ...

我有三个实施IMyInterface的课程:MyClass1MyClass2MyClass3

我有一个只读字典:

private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
    { typeof(MyClass1), typeof(FunnyClass1) },
    { typeof(MyClass2), typeof(FunnyClass2) },
    { typeof(MyClass3), typeof(FunnyClass3) },
};

我有另一个界面IFunnyInteface<T> where T : IMyInterface

我有一个方法:

public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

我正在尝试调用FunnyClasses的构造函数并将其作为参数插入myClass对象。我不想知道它是哪个对象:我只想用MyClass作为参数来实例化一些FunnyClass。

当我调用ConvertToFunnyClass时会发生什么,T的类型为IMyInterface,当我尝试将其强制转换为FunnyInterface<T>时,它表示我无法转换FunnyClass1例如,FunnyInterface<IMyInterface>

我目前的解决方法(不是一个漂亮的解决方法)是:

public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

我不喜欢它,因为返回类型是dynamic,所以当我从其他地方访问它时,我不知道它是什么类型,我失去了intellisense和东西。我也不知道任何性能影响。

任何线索?

提前致谢!

解决

当我使用C#4.0时,我可以使用协方差(仅限输出位置)停止输出错误,因此我将IFunnyInterface更改为

IFunnyInteface<out T> where T : IMyInterface

谢谢大家的回复。

2 个答案:

答案 0 :(得分:1)

基本上,您的问题是您要将FunnyInterface<T>转换为FunnyInterface<IMyInterface>。正如已多次提到的(一个例子是here,更多信息here),这在大多数情况下都无效。仅在.NET 4中,当泛型类型是接口或委托,并且类型参数已显式声明为inout的变体时,您是否可以执行此转换。

FunnyInterface实际上是一个界面吗?

答案 1 :(得分:1)

thecoop答案指出你为什么不能这样做。

问题的清洁解决方案(除了使用动态)将是一个基本的非泛型接口:

public interface IFunnyInterfaceBase
{
}

public interface IFunnyInteface<T> : IFunnyInterfaceBase 
    where T : IMyInterface
{
}

您需要将您在该代码中使用的方法签名从IFunnyInteface移动到IFunnyInterfaceBase。

这样你就能写出这样的东西:

MyClass2 c2 = new MyClass2();
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass();

你在代码中遇到的异常不是由于扩展方法签名本身(方法很好)..它是由你的左值类型(用于存储其返回的变量的类型)产生的值)!

显然此解决方案仅适用于您修改IFunnyInterface源代码的情况!