请考虑以下情形。我有许多共享一个公共基类的类,我为每个派生类定义了一个automapper映射。像这样:
class A : Base {}
class B : Base {}
class ContractA : ContractBase {}
class ContractB : ContractBase {}
void Foo()
{
Mapper.CreateMap<A, ContractA>();
Mapper.CreateMap<B, ContractB>();
}
到目前为止一切顺利。但现在我想创建一个这样的方法:
ContractBase Foo()
{
Base obj = GetObject();
return Mapper.???
}
问题是所有AutoMapper的Map变体都要求我在编译时知道目标类型,或者在运行时使用该类型的对象。这非常令人沮丧,因为我为每种源类型只定义了一个映射。 AutoMapper应该能够仅根据源类型推断目标类型。
这有什么好办法吗?我想避免创建将源类型映射到目标类型的字典。虽然这可行,但这意味着我基本上必须为每种源类型定义两个映射。
答案 0 :(得分:11)
您可以访问存储在AutoMapper中的映射:
ContractBase Foo() {
Base obj = GetObject();
var sourceType = obj.GetType();
var destinationType = Mapper.GetAllTypeMaps().
Where(map => map.SourceType == sourceType).
// Note: it's assumed that you only have one mapping for the source type!
Single().
DestinationType;
return (ContractBase)Mapper.Map(obj, sourceType, destinationType);
}
答案 1 :(得分:3)
您可以转过来并要求Base
为您提供映射合同:
ContractBase Foo() {
Base obj = GetObject();
return obj.ToContract();
}
使用此代码:
abstract class Base {
public abstract ContractBase ToContract();
}
class A : Base {
public override ContractBase ToContract() {
return Mapper.Map<A, ContractA>(this);
}
}
class B : Base {
public override ContractBase ToContract() {
return Mapper.Map<B, ContractB>(this);
}
}
更新:如果您必须将逻辑与类分开,则可以使用访问者:
ContractBase Foo() {
Base obj = GetObject();
var visitor = new MapToContractVisitor();
obj.Accept(visitor);
return visitor.Contract;
}
这就是它的样子:
abstract class Base {
public abstract void Accept(IBaseVisitor visitor);
}
class A : Base {
public override void Accept(IBaseVisitor visitor) {
visitor.Visit(this);
}
}
class B : Base {
public override void Accept(IBaseVisitor visitor) {
visitor.Visit(this);
}
}
interface IBaseVisitor {
void Visit(A a);
void Visit(B b);
}
class MapToContractVisitor : IBaseVisitor {
public ContractBase Contract { get; private set; }
public void Visit(A a) {
Contract = Mapper.Map<A, ContractA>(a);
}
public void Visit(B b) {
Contract = Mapper.Map<B, ContractB>(b);
}
}
现在,所有映射器逻辑都在MapToContractVisitor
类中,而不在Base
层次结构类中。
答案 2 :(得分:1)
我认为Mapper.DynamicMap()
及其各种重载是您正在寻找的。 p>