簡體   English   中英

如何使用自動映射器將對象映射到未知的目標類型?

[英]How can I use Automapper to map an object to an unknown destination type?

請考慮以下情形。 我有許多共享一個公共基類的類,並且為每個派生類定義了一個自動映射器映射。 像這樣:

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應該能夠推斷出目標類型。

有什么好辦法解決嗎? 我想避免創建將源類型映射到目標類型的字典。 盡管這可行,但這實際上意味着我必須為每種源類型定義兩個映射。

您可以訪問存儲在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);
}

您可以將其轉過來並要求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層次結構類中。

我認為您正在尋找Mapper.DynamicMap()及其各種重載。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM