2

我真的搜索了所有协方差问题,没有什么像我的问题。

我有一个用户控件(这个类不能是通用的,原因很明显),它看起来像这样:

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

4 回答 4

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();
      }
    }
  }
于 2013-02-06T15:11:35.367 回答
1

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

协方差:IInterface<out T>

逆变:IInterface<in T>

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

于 2013-02-06T13:41:33.120 回答
0

H.alex is right, best thing would be to move the generic bit on a different layer so you can make the class generic and then have generic class members rather than objects. The class must be able to infer the generic type or you'll have to write something like:

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;
    }    
}

which is clearly not maintainable as you have to take care of mapping all members on the new instance.

于 2013-02-06T14:01:36.010 回答
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>;
   }
}
于 2013-02-06T12:32:38.297 回答