2013-12-06 2 views
0

У меня есть ковариантная/контравариантная проблема с дженериками. Вот код, что я пытаюсь сделать:Утилизация производного объекта на базовый объект с помощью генериков

в рамочном 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>. Как я могу обойти это? не

Foot Примечание: Там нет никаких проблем инициализации (т.е. в словаре), я просто не сочинительство всего кода, который не Релевент к этому вопросу.

ответ

2

Экземпляр OverParam является AOverClass<Param> по определению.

Но вы пытаетесь направить этот экземпляр OverParam на номер AOverClass<IBase>. Это не удается.

Теперь только потому, что любой

Param "является" IBase

мы можем или мы не можем сделать вывод, что каждый

AOverClass<Param> "является" AOverClass<IBase>

?

Ответ: Это работает точно, если AOverClass<T> является ковариантны в T. Единственными типами, которые могут быть ковариантными (отмеченными out перед параметром типа T) в текущей версии C# и .NET, являются типы интерфейсов и типы делегатов. Но 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 контрвариантно. Поэтому, даже если язык разрешил типы классов быть ковариантными, он не будет применяться в вашем случае. Это указывает на то, что в ваших предположениях есть что-то принципиально неправильное.

+0

Спасибо за информацию ... Итак, вы говорите, что мне нужно изменить свой абстрактный класс на интерфейс, а затем использовать параметр конструктора как 'out'. Таким образом, я смогу использовать ковариацию и добиться своей цели? Я дам ему попробовать ... –

Смежные вопросы