非泛型类中的C#协方差

时间:2013-02-06 12:17:13

标签: c# covariance

我真正搜索了所有的协方差问题,看起来没什么问题。

我有一个用户控件(由于显而易见的原因,这个类不能通用),它看起来像这样:

class MyUserControl : UserControl
{
    private BaseDao<object> _dao;
    private AppointmentMapping<object> _mapping;

    // I need these 2 generics to type safe the mapping/dao relation
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping)
   {
        // These two dont work. even with safe and unsafe casting.
        _dao = dao;
        _mapping = mapping;
   }
}

我已经尝试为协方差,接口等存储委托。它只是不存储对象! 我怎样才能实现这一目标?使用Java可以轻松实现这一点。

4 个答案:

答案 0 :(得分:2)

尝试以下方法。 我们的想法是在使用时捕获T并将其存储在“知道以后要做什么”的类中。然后通过接口引用类中的项目(省略类型信息)。 稍后通过界面调用存储的值。这样,您就不需要重构通用类来实现某些接口。

class MyUserControl : UserControl
  {

    // hold a reference to the helper - no generics needed here -> "covariant"
    private IHelper helper;

    // I need this 2 generics to type safe the relation between the mapping and the dao
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping) {
      // "pass <T>" for later usage
      this.helper = new HelperImpl<T>(dao, mapping);
    }

    // use the stored values...
    public void doStuff() {
      helper.doStuff();
    }

    // the non generic interface
    private interface IHelper
    {
      void doStuff();
    }

    // a generic implementation for storing the items *and* using them.
    private sealed class HelperImpl<T> : IHelper
    {
      private readonly BaseDao<T> dao;
      private readonly AppointmentMapping<T> mapping;

      public HelperImpl(BaseDao<T> dao, AppointmentMapping<T> mapping) {
        this.dao = dao;
        this.mapping = mapping;
      }

      public void doStuff() {
        this.dao.foo();
        this.mapping.foo();
      }
    }
  }

答案 1 :(得分:1)

使用协方差和逆变是必要的接口!

协方差:IInterface<out T>

逆变:IInterface<in T>

检查此链接以获取更多信息: http://weblogs.asp.net/dixin/archive/2009/08/31/understanding-csharp-covariance-and-contravariance-3-samples.aspx

答案 2 :(得分:0)

据我所知,这是不可能的。

就像塞巴斯蒂安所说,你能做的就是

class MyUserControl : UserControl
{
    private object _dao;
    private object _mapping;

    // I need this 2 generics to type safe the relation between the mapping and the dao
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping)
   {
        _dao = dao;
        _mapping = mapping;
   }


   public BaseDao<T> GetDao<T>()
   {
       return _dao as BaseDao<T>;
   }

   public AppointmentMapping<T> GetAppointmentMapping<T>()
   {
       return _mapping as AppointmentMapping<T>;
   }
}

答案 3 :(得分:0)

H.alex是对的,最好的办法就是将通用位移到另一个层上,这样你就可以使类具有通用性,然后拥有泛型类成员而不是对象。该类必须能够推断泛型类型,或者您必须编写如下内容:

public class BaseDao<T>
{
    public T Item { get; set; }
}

public class TestClass
{
    private BaseDao<object> _dao;

    public void RegisterPersistence<T>(BaseDao<T> dao)
    {
        _dao = Activator.CreateInstance<BaseDao<object>>();
        //need to map each member of BaseDao
        _dao.Item = dao.Item;
    }    
}

显然无法维护,因为您必须负责映射新实例上的所有成员。