在非泛型类中的C#协方差
我真的在所有的协方差问题中搜索,没有什么看起来像我的问题。在非泛型类中的C#协方差
我有一个用户控件(这个类不能是通用的,出于显而易见的原因),它看起来像这样:
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实现。
请尝试以下操作。 这个想法是在使用时捕获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();
}
}
}
谢谢!做成它,结果是sweeeeeeeeet。 – Stew
如果这是可能的,那么也可以将原始对象重新分成非通用基础,这些基础可以直接存储在用户控件中。 –
这是尽我所知不可能的。
就像塞巴斯蒂安说,你可以做的是有
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>;
}
}
要使用协方差和逆变需要一个接口!
协方差:IInterface<out T>
逆变:IInterface<in T>
检查此链接了解更多信息: http://weblogs.asp.net/dixin/archive/2009/08/31/understanding-csharp-covariance-and-contravariance-3-samples.aspx
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;
}
}
这显然不是维护,你必须采取所有映射成员的新实例的照顾。
这不是一个协方差,它是一个不变量,你将无法将 –
转换为真,在这里添加一个协变接口,该类需要包含约束(来自接口)
这个问题似乎与'UserControl'无关。它可以发生在任何类。你可以考虑编辑这个问题,使它更“通用”... –
我不知道BaseDao和AppointmentMapping的定义,但如果它们确实是泛型类,泛型参数没有共同/反对差异在C# – SWeko
关键是你不告诉你以后如何访问这些字段。当然,将它们存储为'object'将起作用。如果以后需要在另一个代码块中访问这些字段,则需要再次使用'',然后您可以强制转换为对应于正确的实现,或将使用该字段的代码注册到委托中(类型为Action) ,例如并在稍后执行。否则,使BaseDoa和AppointmentMapping实现非通用接口并将其用于字段类型。 –
Sebastian