私は現在、次のマッピングを持っています:
Mapper.CreateMap<Journal, JournalDto>();
現在、Journal
にはRefTypeID
という名前のメンバーが含まれており、対応する値はデータベース内の別のテーブルに存在します。この値を調べるために、単純なint -> string
リクエストを処理するサービスがあります。自動マッパー構成は現在、プログラムの開始時に静的クラスで行われます。マッピングコードをDIコンテナに挿入されるクラスに移動しても大丈夫ですか、それとももっと良い方法がありますか?
これが私がそれを解決した方法です:
IMappingCreator
インターフェースを定義しました。
public interface IMappingCreator
{
void CreateMappings();
}
私は先に進み、そのインターフェイスを使用してクラスを実装しました(MEFをDIコンテナーとして使用しており、そこから属性が取得されます)。これはIMappingCreator
としてDIコンテナーに配置されます。
[Export(typeof(IMappingCreator))]
public class Mapping : IMappingCreator
{
private readonly IRefTypesLookup iRefTypesLookup;
[ImportingConstructor]
public Mapping(IRefTypesLookup rtl)
{
iRefTypesLookup = rtl;
}
public void CreateMappings()
{
Mapper.CreateMap<Journal, DisplayJournal>().AfterMap((j, dj) => dj.RefTypeName = iRefTypesLookup.Lookup(j.RefTypeID));
}
}
最後に、アプリケーションの起動時に、コンテナー内のそのインターフェイスのすべてのインスタンスをフェッチし、それらに対してCreateMappings
メソッドを呼び出します。
var mappings = container.GetExportedValues<IMappingCreator>();
foreach (IMappingCreator mc in mappings)
{
mc.CreateMappings();
}
これにより、すべての作成が1つの場所で行われるため、初期設定が非常に簡単になり、必要な数のマッピングクリエーターを作成できます(ただし、プロジェクトごとに1回程度、必要なすべてのサービスを取得するために、それらを最小限に抑える必要があります。そのプロジェクトの特定のタイプをマッピングするため)。
より良い方法は、カスタマーリゾルバーを使用することです。マッピング構成は静的であることが意図されているため、カスタムリゾルバーは単一のメンバーにマッピングを提供することを目的としています。
Mapper.Initialize(cfg => {
cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type));
cfg.CreateMap<Journal, DisplayJournal>()
.ForMember(dest => dest.RefTypeName,
opt => opt.ResolveUsing<RefTypeNameResolver>());
});
次に、リゾルバは次のようになります。
[Export(typeof(IRefTypeNameResolver))]
public class RefTypeNameResolver : ValueResolver<Journal, string>, IRefTypeNameResolver
{
private readonly IRefTypesLookup iRefTypesLookup;
[ImportingConstructor]
public RefTypeNameResolver (IRefTypesLookup rtl)
{
iRefTypesLookup = rtl;
}
protected override string ResolveCore(Journal source)
{
return iRefTypesLookup.Lookup(source.RefTypeID);
}
}
構成は1回実行する必要があります。そのため、構成APIは実行APIへのフックを提供します(タイプコンバーター、値リゾルバーなど)。
静的クラスIMappingEngine
を使用する代わりに、Mapper
に依存することができます。
ここにそれについての素晴らしいブログ投稿があります: 依存性注入によるAutoMapperのモックアウト
これが最新の方法です...
私は個人的に自動マッピングをリポジトリではなくコントローラに追加していますが。このようにして、異なるコントローラーに同じリポジトリーを使用し、異なるマッピングを持つことができます。同じ概念ですが、リポジトリではなくコントローラにIMapper
を挿入するだけです。