如何使用Automapper将对象映射到未知的目标类型?
考虑以下情况。我有许多共享公共基类的类,并为每个派生类定义了一个自动映射器映射。像这样的:如何使用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的地图变种的要求,我无论是在编译时知道目标类型或具有该类型在运行时可用的对象。这是非常令人沮丧的,因为我只为每个源类型定义了一个映射。 AutoMapper应该能够推断仅给定源类型的目标类型。
有没有什么好办法解决这个问题?我想避免创建一个字典映射源类型到目标类型。虽然这会起作用,但这意味着我基本上必须为每个源类型定义两个映射。
你可以访问存储在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);
}
由于我们没有'Mapper.GetAllTypeMaps()',所以此解决方案在版本5中不起作用 – 2016-07-09 09:58:00
@MohammadDayyan:感谢您的信息。也许[这个问题](https://github.com/AutoMapper/AutoMapper/issues/1252)将有所帮助。 – 2016-07-09 12:27:06
我认为Mapper.DynamicMap()
和它的各种过载是你在找什么。
看来这些方法只是一个对象映射到另一个(而不是返回一个新的对象)。他们仍然需要目标类型。 – 2010-10-05 18:53:58
你可以把它周围,并要求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);
}
}
UPDATE:如果你必须单独从班级逻辑,你可以使用一个访客:
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
层次结构类。
这很聪明,但不幸的是它不适合我们。有问题的类将消息表示给不同的系统。他们并不相互了解对方。 – 2010-10-05 20:36:30
好吧,让我再试一次.... – 2010-10-05 20:45:00
这并不能真正解决原来的问题。我的问题不是我看不到映射的方法,而是我想避免重复的工作。有了这个解决方案,我每次添加一对新类时都必须做两件事。首先,我必须定义自动映射器映射,然后我必须创建一个访问者方法。我希望有一种方法来定义_just_映射,而不是别的。 – 2010-10-06 15:36:38
使用valueinjecter.codeplex.com – Omu 2010-10-05 20:21:09