2016-02-03 5 views
12

私はしばらくの間、.NetアプリでAutomapperとAutofacを使ってきました。 APIが変更されたと私はトラブルの新しいAPIへの翻訳を持っていますAutomapper(4.2)の最新のビルドでAutofacとAutomapperの新しいAPI - ConfigurationStoreがなくなった

builder.RegisterAssemblyTypes(typeof (OneOfMyMappingProfiles).Assembly) 
     .Where(t => t.IsSubclassOf(typeof (Profile))) 
     .As<Profile>(); 

builder.Register(ctx => new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers)) 
     .AsImplementedInterfaces() 
     .SingleInstance() 
     .OnActivating(x => 
     { 
      foreach (var profile in x.Context.Resolve<IEnumerable<Profile>>()) 
      { 
       x.Instance.AddProfile(profile); 
      } 
     }); 

builder.RegisterType<MappingEngine>() 
      .As<IMappingEngine>().SingleInstance(); 

:私はそれらをこのように構成されました。 ConfigurationStoreは存在しなくなりました。ドキュメントによれば、IOCに登録する方法は次のようになります。

var profiles = 
     from t in typeof (AutoMapperRegistry).Assembly.GetTypes() 
     where typeof (Profile).IsAssignableFrom(t) 
     select (Profile)Activator.CreateInstance(t); 

    var config = new MapperConfiguration(cfg => 
    { 
     foreach (var profile in profiles) 
     { 
      cfg.AddProfile(profile); 
     } 
    }); 

    For<MapperConfiguration>().Use(config); 
    For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance)); 

しかし、StructureMapを使用しています。これの前半は問題ありませんが、 "For <> .Use()"部分の翻訳方法はわかりません。オートファックではどうすればいいですか?

答えて

18

OK。それを取り除いた。ここでは、交換されています

var profiles = 
     from t in typeof(LocationMappingProfile).Assembly.GetTypes() 
     where typeof(Profile).IsAssignableFrom(t) 
     select (Profile)Activator.CreateInstance(t); 

     builder.Register(ctx => new MapperConfiguration(cfg => 
     { 
      foreach (var profile in profiles) 
      { 
       cfg.AddProfile(profile); 
      } 
     })); 

     builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>(); 

UPDATE

ここでは、プロファイルの一例です。スーパーシンプル。この場合、私は1つのマッピングしか持たない。しかし、私は他を追加することができます。私はエンティティによってそれらを論理的に一緒に保つようにします。したがって、この場合、将来のProviderDetailへのマッピングはこのファイルになります。別のエンティティへのマッピングは、別のmappingprofileクラスにあります。プロファイルクラスに注入何:

public class ProviderMappingProfileTests 
{ 
    [Fact] 
    public void CreateMap_ProviderDetailToProviderQueryResult_IsValid() 
    { 
     var config = new MapperConfiguration(cfg => 
      cfg.CreateMap<ProviderDetail, ProviderListItem>() 
      ); 

     config.AssertConfigurationIsValid(); 
    } 
} 
+0

はあなたのプロファイルのいずれかを表示することができますか? IMapperConfigurationをプロファイルコンストラクタに挿入しますか? – BBauer42

+0

ありがとう!私はGitHub上で([Autofacで新しいバージョンのAutoMapperを設定する際のこのスレッド](https://github.com/AutoMapper/AutoMapper/issues/1109)も非常に役に立ちました。 – BBauer42

+0

迅速なフォローアップの質問。どこでどのように構成を有効にすることが有効ですか? – BBauer42

1

Iが溶液上に合意した:

public class ProviderMappingProfile : Profile 
{ 
    protected override void Configure() 
    { 
     CreateMap<ProviderDetail, ProviderListItem>(); 
    } 
} 

アップデート2

ここでは、マッピングが正しいことを証明する試験の例ではありません。反射を使用する代わりに、私たちは以下のようにすることはできませんか?ここでAutofac登録

builder.Register(c => AutoMapperConfig.RegisterAutoMapper()).As<IMapper>() 
    .InstancePerLifetimeScope().PropertiesAutowired().PreserveExistingDefaults(); 
+1

プロフィールを追加すると、時間が経つにつれてこれを維持するのが難しくなります。プロフィールの数が少ないと、これはより良い結果を出すかもしれませんが、大きなプロジェクトでは何かを追加するのを忘れるための場所です –

+0

合意......ありがとうございました –

0

public static IMapper RegisterAutoMapper() 
{ 
    var config = new MapperConfiguration(cfg => 
    { 
     cfg.AddProfile<ApiMappingProfile1>(); 
     cfg.AddProfile<ApiMappingProfile2>(); 
     // Add all your profiles 
    }); 
    var mapper = config.CreateMapper(); 
    return mapper; 
} 

は、私の作品はほとんど修正、です。ロードされたすべてのアセンブリをスキャンし、それらからすべてのAutoMapperプロファイルをロードします。

var autoMapperProfileTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes().Where(p => typeof(Profile).IsAssignableFrom(p) && p.IsPublic && !p.IsAbstract)); 
    var autoMapperProfiles = autoMapperProfileTypes.Select(p => (Profile)Activator.CreateInstance(p)); 
    builder.Register(ctx => new MapperConfiguration(cfg => 
    { 
     foreach (var profile in autoMapperProfiles) 
     { 
      cfg.AddProfile(profile); 
     } 
    })); 
    builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>().PropertiesAutowired(); 

AutoMapperの組み込みスキップをスキップするには、抽象クラスとプライベートクラスをフィルタリングする必要があります。

4

あなたのアセンブリ内のすべてのカスタムプロファイルの動的な登録で、AutofacてAutomapperを登録するもう一つの興味深い方法。

ここでは、必要なすべてのアセンブリのプロファイルを登録します。

builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Program))) 
    .Where(t => t.BaseType == typeof(Profile) 
       && !t.IsAbstract && t.IsPublic) 
    .As<Profile>(); 

そして、ここで、あなたはそれらの解決:、また

builder.Register(ctx => new MapperConfiguration(cfg => 
{ 
    foreach (var profile in ctx.Resolve<IEnumerable<Profile>>()) 
     cfg.AddProfile(profile); 
})); 

builder.Register(ctx => ctx.Resolve<MapperConfiguration>() 
          .CreateMapper()) 
     .As<IMapper>() 
     .SingleInstance(); 

をプロファイル内の内部依存関係を解決する代わりに

.CreateMapper() 

.CreateMapper(ctx.Resolve) 

を使用することができます。しかし、削除する必要があります

.SingleInstance() 

登録します。

そしてここところで使い方です:

public SomeAutowiredClass 
{ 
     public IMapper Mapper { get; set; } 

     public void SomeMethod(SomeModel model){ 
      Mapper.Map<AnotherModel>(model) 
     } 
} 
+0

私はそれをコンテナを使用するので、プロファイルを解決します。 'ForEach'の呼び出しは個人的な拡張方法ですが、 –

+0

ああ良いキャッチ、私はそれに気付かなかった。それは "Castle.Core"アセンブリからのものです。私は動的プロキシのためにそれを使用しています。 –

関連する問題