2011-10-24 28 views
8

ネストされたマッピングのwikiページを読みましたが、複数のネストレベルが気に入らないようです。私は次のマップを作成し、クラスを定義しています。Automapperのネストされたマッピング

AutoMapper.Mapper.CreateMap<Address, AddressDTO>(); 
AutoMapper.Mapper.CreateMap<MatchCompanyRequest, MatchCompanyRequestDTO>(); 

public class MatchCompanyRequest 
{ 
    Address Address {get;set;} 
} 

public class MatchCompanyRequestDTO 
{ 
    public CompanyInformationDTO {get;set;} 
} 

public class CompanyInformationDTO {get;set;} 
{ 
    public string CompanyName {get;set;} 
    public AddressDTO Address {get;set;} 
} 

しかし、次のコード...

// works 
matchCompanyRequestDTO.companyInformationDTO.Address = 
    AutoMapper.Mapper.Map<Address, AddressDTO>(matchCompanyRequest.Address); 

// fails 
matchCompanyRequestDTO = 
    AutoMapper.Mapper 
     .Map<MatchCompanyRequest, MatchCompanyRequestDTO>(matchCompanyRequest); 

は、この深いネストの仕事をして、私はそれが不適切に設定されていますか?または、この種のネスティングはまだサポートされていませんか?

- 編集

興味がある人のために、私はのDTOの制御ではないです。

答えて

6

これらのオブジェクトが同じネストレベルにあるため、アドレスからCompanyInformationDTOへのマッピングが欠落しています。

MatchCompanyRequest - >MatchCompanyRequestDTOのマップが作成されていますが、AddressからCompanyInformationDTOにマップできるかどうかはわかりません。

は、だからあなたのMatchCompanyRequestDTOが実際にあなたのCompanyInformationDTOと同じ宣言を持つことができます:あなたが自動マッピングを使用する場合はもちろんの

public class MatchCompanyRequestDTO 
{ 
    public string CompanyName {get;set;} 
    public AddressDTO Address {get;set;} 
} 

これをあなただけに影響します。

public class CustomResolver : ValueResolver<Address, CompanyInformationDTO> 
{ 
    protected override CompanyInformationDTO ResolveCore(Address source) 
    { 
     return new CompanyInformationDTO() { Address = Mapper.Map<Address, AddressDTO>(source) }; 
    } 
} 
// ... 

AutoMapper.Mapper.CreateMap<MatchCompanyRequest, MatchCompanyRequestDTO>() 
    .ForMember(dest => dest.companyInformationDTO, opt => opt.ResolveUsing<CustomResolver>().FromMember(src => src.Address)); // here we are telling to use our custom resolver that converts Address into CompanyInformationDTO 
+0

'Mapper'インスタンス? – dougajmcdonald

+0

次に、 'AutoMapper.Mapper'の代わりにインスタンスを使用しますか?私は本当に知りません - 私はAutoMapperを使用して以来何年もありました... – Bartosz

+0

最近、プロファイルを作成して設定にフィードするのがベストプラクティスです。そうすればDIを使用でき、静的インスタンスは使用できなくなります。私はこれを共通の解決策と見なし、現在のベストプラクティスにどのように適合するのか不思議です。 – dougajmcdonald

0

を代わりに次のことを考えてみましょう:

public class MatchCompanyRequest 
{ 
    Address Address {get;set;} 
} 

public class MatchCompanyRequestDTO 
{ 
    public string Name {get;set;} 
    public AddressDTO Address {get;set;} 
} 

public class AddressDTO 
{ 
    .... 
} 

あなたのDTOオブジェクトが同じを持っている必要がありますのDTOを代わりに固定しなければならないように、のは、とにかく試してみましょうあなたはまだ手動でマップを設定することができますが、それはそうですAutoMapperでデフォルトのマッピング規則を使用するためのドメインオブジェクトとして使用します。

これを見てください:https://github.com/AutoMapper/AutoMapper/wiki/Projectionそれはあなたのための投影を説明します、あなたはあなたがそれを持っている方法で動作するようにカスタマイズすることができます。

4

重要なことは、スタックオーバーフローの問題を予感させるために、ナビゲーションの深さを定義することです。この可能性を想像してみて:

あなたは2つのエンティティユーザーとN×N個のモデルで通知(そして あなたはのDTOがそれを表現するためにオブジェクトを持っている)、あなたのユーザーの自動マッパー を持って集合なしMAXDEPTHあなたにマッパー表現、 "ヒューストン私たちは 問題があります" :)。

以下のコードはすべてのマッパーでこれを解決するワーキングアラウンドを示しています。必要ならば、各マッパーに定義することができます。あなたは、静的を使用していない場合は、このようなものが設定される方法Like this Question

ソリューション1(グローバル定義)

public class AutoMapperConfig 
{ 
    public static void RegisterMappings() 
    { 
     Mapper.Initialize(mapperConfiguration => 
     { 
      mapperConfiguration.AddProfile<DomainModelToYourDTOsMappingProfile>(); 
      mapperConfiguration.AddProfile<YourDTOsToDomainModelMappingProfile>(); 
      mapperConfiguration.AllowNullCollections = true; 
      mapperConfiguration.ForAllMaps 
      (
       (mapType, mapperExpression) => 
       { 
        mapperExpression.MaxDepth(1); 
       }); 
      }); 
     } 
    } 

(各マッパー用)ソリューション2

public class AutoMapperConfig 
{ 
    public static void RegisterMappings() 
    { 
     Mapper.CreateMap<User, DTOsModel>() 
       .MaxDepth(1); 
    } 
} 
+1

OPには正解ではありませんが、本当に良い情報です。ありがとう! – Mathter

+0

ありがとう@マター! –

関連する問題