我试图使所有这些映射器类都有一个共同的基础:
// base
class BaseInput { public string BaseInputValue { get; set; } }
class BaseOutput { public string BaseOutputValue { get; set; } }
interface IMapper<InputType, out OutputType>
where InputType : BaseInput
where OutputType : BaseOutput
{
OutputType Map(InputType input);
}
// example implementation
class Input : BaseInput { public string InputValue { get; set; } }
class Output : BaseOutput { public string OutputValue { get; set; } }
class MyMapper : IMapper<Input, Output>
{
public Output Map(Input input)
{
// custom mapping done here to Output
return new Output { /* mapping */ };
}
}
这段代码可以创建一个新的映射器,并将其分配给基本编译器:
var myBaseMapper = (IMapper<BaseInput, BaseOutput>) new MyMapper();
但是我遇到了运行时错误:
无法将类型为“ MyMapper”的对象转换为类型为“ IMapper`2 [UserQuery + BaseInput,UserQuery + BaseOutput]”的对象。
如果我将
IMapper
减小为IMapper<out OutputType>
,则可以正常工作,但这需要在MyMapper.Map
中进行强制转换,这在每个映射器类中都必须执行,这有点烦人。另外,这使我失去了决定使用哪个Mapper用于BaseInput
的信息,因此必须在其他位置进行定义。是使用C#无法做到这一点还是有类似的方法吗?如果没有,我将不得不重新考虑我的设计。
最佳答案
您无法执行此操作,因为它没有意义,您的界面在InputType
参数中是相反的(或者相反,如果您在该参数中添加了in
关键字,则是相反的)。要了解为什么这没有意义,让我们看一下您的示例:
您希望将IMapper<Input, Output>
的实现分配给IMapper<BaseInput, BaseOutput>
。假设我们创建了一个新的BaseInput
子类,我们将其称为MoreInput
:
class MoreInput : BaseInput
{
public string LotsOfInput { get; set; }
}
好的,现在我们假设有一个方法,其主体看起来像这样(而您想要的实际上是起作用的):
IMapper<BaseInput, BaseOutput> mapper = new MyMapper();
mapper.Map( new MoreInput() );
好了,在这一点上没什么问题:
IMapper<BaseInput, BaseOutput>
有一个Map
方法,该方法接受BaseInput
作为其参数,而MoreInput
是BaseInput
,因此我们对Map
的调用是有效的。除非不是,因为我们真正调用的
Map
方法期望以Input
作为其参数,而MoreInput
不是Input
。我们破坏了类型系统。这就是编译器告诉您的时间,它不允许您隐式进行分配:转换不安全。编译器无法保证您期望的类型就是您获得的类型。
关于c# - 使用协方差和多个通用参数时强制转换为基本接口(interface),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33243300/