使用泛型将派生对象转换为基础对象

时间:2013-12-06 10:12:09

标签: c# generics reflection casting

我对泛型有一个协变/逆变问题。 这是我正在尝试做的代码:

在框架DLL中:

namespace framework {
    public interface IBase 
    {
        //Some code...
    }

    public abstract class AOverClass<T> : IBase where T : IBase
    {
        public AOverClass(T pObject)
        {
            //Some code
        }
        //Some code...
    }

    public class workerClass 
    {
        public Dictionary<Type, Type> ObjDictionary;
        public AOverClass<IBase> GetOverObj(IBase initObj){

            // Get the over Obj type from a dictionary that was loaded previously
            // the dictionary contains KVP of <Type, Type> then using Reflection 
            // to initialise a new OverObj

            Type t = Dictionary[initObj.GetType()];
            Type[] _typesParamsConstructor = new Type[1];
            _typesParamsConstructor[0] = initObj.GetType();
            Object[] _valParamsConstructor = new Object[1];
            _valParamsConstructor [0] = initObj;

            // BIG ISSUE HERE

            return (AOverClass<IBase>)t.GetConstructor(_typesParamsConstructor).Invoke(_valParamsConstructor);
        }
    }
}

在引用框架DLL的应用程序中:

namespace myApp {
    public class Param : framework.IBase, myApp.IOtherNeeded
    {
        //Some code
    }

    public class OverParam : framework.AOverClass<Param>
    {
        public OverParam(Param pObject) :base(pObject)
        {
            //Some code...
        }
    }

    public class App
    {
        private framework.workerClass _wc;
        public void Init()
        {
            _wc = new framework.workerClass();
            _wc.ObjDictionary.Add(typeof(Param), typeof(OverParam));
        }

        public void Run()
        {
            _wc.GetOverObj(new Param());
        }
    }
}

workerClass抛出一个异常,它无法将OverParam强制转换为AOverClass<IBase>。 我该如何解决这个问题?

脚注: 没有初始化问题(即字典),我只是没有编写所有与此问题无关的代码。

1 个答案:

答案 0 :(得分:2)

根据定义,OverParam的实例是AOverClass<Param>

但是您尝试将OverParam的实例投射到AOverClass<IBase>。那失败了。

现在只是因为任何

  

Param“是”IBase

我们能否或不能得出每一个

的结论
  

AOverClass<Param>“是”AOverClass<IBase>

答案是:如果AOverClass<T>中的T 协变 ,则可以正常运行。在当前版本的C#和.NET中,唯一可以协变的类型(在类型参数out之前标记为T)是接口类型和委托类型。但AOverClass<T> 类类型

另外,当我们看你的班级时:

public abstract class AOverClass<T> : IBase where T : IBase
{
    public AOverClass(T pObject)  // an "in" parameter of type T here! :-(
    {
        //Some code
    }
    //Some code...
}

我们发现你违反了T。因此,即使语言允许类类型是协变的,它也不适用于您的情况。这表明您的假设存在根本性的错误。