web-dev-qa-db-ja.com

Automapperと依存性注入

私は現在、次のマッピングを持っています:

Mapper.CreateMap<Journal, JournalDto>();

現在、JournalにはRefTypeIDという名前のメンバーが含まれており、対応する値はデータベース内の別のテーブルに存在します。この値を調べるために、単純なint -> stringリクエストを処理するサービスがあります。自動マッパー構成は現在、プログラムの開始時に静的クラスで行われます。マッピングコードをDIコンテナに挿入されるクラスに移動しても大丈夫ですか、それとももっと良い方法がありますか?

22
Femaref

これが私がそれを解決した方法です:

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回程度、必要なすべてのサービスを取得するために、それらを最小限に抑える必要があります。そのプロジェクトの特定のタイプをマッピングするため)。

9
Femaref

より良い方法は、カスタマーリゾルバーを使用することです。マッピング構成は静的であることが意図されているため、カスタムリゾルバーは単一のメンバーにマッピングを提供することを目的としています。

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へのフックを提供します(タイプコンバーター、値リゾルバーなど)。

16
Jimmy Bogard

静的クラスIMappingEngineを使用する代わりに、Mapperに依存することができます。

ここにそれについての素晴らしいブログ投稿があります: 依存性注入によるAutoMapperのモックアウト

14
Martin R-L

これが最新の方法です...

https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/

私は個人的に自動マッピングをリポジトリではなくコントローラに追加していますが。このようにして、異なるコントローラーに同じリポジトリーを使用し、異なるマッピングを持つことができます。同じ概念ですが、リポジトリではなくコントローラにIMapperを挿入するだけです。

4
Gene S