我遇到了一个问题 - 这是我的班级结构
public interface IModel{}
public interface IGenericMapper<T> where T : IModel {...}
public class ActualModel:IModel {...}
public class ActualMapper: IGenericMapper<ActualModel> {...}
我初始化映射器的实际代码是:
IGenericMapper<IModel> mapper;
mapper= new ActualMapper();
它无法编译。我收到了错误
无法将类型'ActualMapper'隐式转换为'IGenericMapper'。 存在显式转换(您是否错过了演员?)
当我使用
进行投射时mapper= new ActualMapper() as IGenericMapper<IModel>;
映射器未正确初始化(它返回为NULL)
我错过了什么 - 因为ActualMapper()
实现了IGeneric
Mapper及其类型impliments`IModel'为什么它不能初始化mapper。
有没有其他方法来构建这个以实现我需要的东西?
非常感谢
注意人们提出的解决方案给了我其他编译错误,因为映射接口具有以下成员
T GetModel(busO bBusinessObject);
busO SetBusObject(T source, busO target);
显然,当它在“out”
声明时,你不能将泛型类型作为输入参数答案 0 :(得分:5)
非常确定你正在通过Generic改变进入协变领域;
试试这个:
public interface IModel{}
public interface IGenericMapper< out T> where T : IModel{}
public class ActualModel : IModel{}
public class ActualMapper : IGenericMapper<ActualModel> {}
然后:
IGenericMapper<IModel> blah = new ActualMapper();
没有'out T'你可以做的最好的事情是:
IGenericMapper<ActualModel> blah = new ActualMapper();
这是一个兔子洞,所以要小心,特别是如果你试图混合这两个:)
http://msdn.microsoft.com/en-us/library/ee207183.aspx
[编辑]
如果您希望能够向下转换通用T
,那么它必须是out
,并且您不能将其用作输入。但是,您可以在实现中将其中的一部分移动到实时;即检查是否可以将其投射到模型类型。
interface IGenericMapper<out TModel, in TKeyOrIdent>
TModel GetModel(TKeyOrIdent bBusinessObject);
void SetModel(object model, TKeyOrIdent target);
答案 1 :(得分:4)
你必须定义
IGenericMapper<out T>
支持您的方案,但这适用于其他限制。
即使IGenericMapper<IModel>
IGenericMapper<ActualModel>
!= ActualModel : IModel
在大多数情况下,拥有一个非通用的基本接口是有意义的。例如,请参阅IList<T>
,它实现了IList
。
然后,您可以选择实现来显式实现接口成员。见List<T>.GetEnumerator() : IEnumerable
假设您可以消除任何地方的投射,请不要使用泛型。我试过它C#根本就没有这个所需的功能。
我建议将IGenericMapper
接口作为IGenericMapper<T>
的基本接口,然后在IGenericMapper
上执行通用代码,最后(并且此时已经有类型)将其强制转换为特定类型。