2016-05-17 17 views
2

DIフレームワークがAutomapperカスタムTypeConverterに依存関係を挿入するには、通常、MapperConfigurationオブジェクトのConstructServicesUsingメソッドを使用します。だから、ASP.NETコアDIで、私はこのようなAutoMapperを設定できることを期待:ASP.NETコアのAutomapper TypeConverterへの依存関係の注入

public static IMapperConfiguration Configure(IServiceProvider provider) 
{ 
    var config = new MapperConfiguration(cfg => { 
     cfg.AddProfile<MyProfile>(); 
     cfg.ConstructServicesUsing(type => provider.GetService(type)); 
    }); 
    config.AssertConfigurationIsValid(); 
    return config; 
} 

MapperConfigurationオブジェクトは、このようにstartup.cs内注射用サービスとして構成されます:

public void ConfigureServices(IServiceCollection services) 
{ 
    //other service configuration omitted for simplicity 

    //Automapper config 
    var provider = services.BuildServiceProvider(); 
    var config = AutoMapperConfig.Configure(provider); 
    services.AddInstance(config); 
} 

そして、依存関係(この場合、Automapper自体)は、このようにTypeConverterコンストラクタに注入されます。

public class MyConverter : ITypeConverter<ThisType, ThatType> 
{ 
    private IMapper _mapper; 

    public MyConverter(IMapperConfiguration mapperConfig) 
    { 
     var mc = mapperConfig as MapperConfiguration; 
     _mapper = mc.CreateMapper(); 
    } 

    public ThatType Convert(ResolutionContext context) 
    { 
     //do something with _mapper here 
    } 
} 

このパターンはいくつかのDIフレームワークで正常に使用されていますが、ASP.NET Coreで動作させることはできません。 Automapperは、ConfigureServicesメソッドが完了した後に.NETによって構築された実際のIServiceProviderインスタンスを取得する必要があるかもしれないと思います。しかし、Configureメソッド(下記参照)まで構成のその部分を延期しても、依存関係はTypeConverterにまだ注入されません。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider) 
{ 
    var config = provider.GetService<IMapperConfiguration>(); 
    config.ConstructServicesUsing(type => provider.GetService(type)); 
} 

だから私の質問は:それはカスタムTypeConvertersへの依存性を注入するようにどのように私はASP.NETのコアとAutomapperを設定しますか。

+1

まだASP.NET 5 beta7またはbeta8で作業していますか?私は 'services.AddInstance'を他のシングルトン登録と一直線に保つために' AddSingleton'に名前を変更したことを覚えています – Tseng

+0

私の悪いことは、RC2の発表にありましたが、それはずっと前にRC1のリリース。 https://github.com/aspnet/Announcements/issues/119 – Tseng

+0

いずれにしてもRC1を使用しています。 –

答えて

3

を次のコードを追加し、私はこれに対する解決策を見つけました問題はの正しい構成にありますファクトリメソッド。

public void ConfigureServices(IServiceCollection services) 
{ 
    //other service configuration omitted for simplicity 

    //Automapper config 
    services.AddSingleton(provider => AutoMapperConfig.Configure(provider)); 
} 

をしかし、決定的に、Automapperは、.NETを使用するように設定する必要があります。@Tsengが指摘したように、IServiceCollection.AddSingletonメソッドを使用すると、それが行われるべき場所である、AutomapperはStartup.csのConfigureServices方法で設定することができますサービスインスタンスを作成するために、コアのActivatorUtilitiesクラス(私のアイデアを与えるためのthis articleにクレジット):この方法で

public static IMapperConfiguration Configure(IServiceProvider provider) 
{ 
    var config = new MapperConfiguration(cfg => { 
     cfg.AddProfile<MyProfile>(); 
     cfg.ConstructServicesUsing(type => ActivatorUtilities.CreateInstance(provider, type)); 
    }); 
    config.AssertConfigurationIsValid(); 
    return config; 
} 

は、Automapperは、カスタムTypeConvertersValueResolversに任意のサービスの依存関係を注入するように構成されています。そのようなサービスがConfigureServicesIServiceCollectionインスタンスにも追加されていることを確認してください。

1

サービスを注入/インスタンス化するには、ファクトリメソッドを使用する必要があります。

services.AddSingleton<IMapperConfiguration>((serviceProvider) => AutoMapperConfig.Configure(serviceProvider)); 

初めてIMapperConfigurationが解決されるまで、あなたがConfigureへの呼び出しを遅らせるこのように。シングルトンなので、アプリケーションコンテナの残りの部分は生き残り、さらにRequestServiceを呼び出すと同じインスタンスが返されます。

編集:

があなたのAutoMapperConfig.Configure方法からconfig.AssertConfigurationIsValid();を削除してみてくださいStartup.cs

public void Configure(IServiceProvider app) 
{ 
    app.VerifyAutoMapperConfig(); 
} 

AutoMapperConfigExtensions.cs

// So one doesn't have to add namespaces to become available 
// inside Startup.cs; Recommended way all middleware register their 
// AddXxx and UseXxx extension methods 
namespace Microsoft.Extensions.DependencyInjection { 
    public static class AutoMapperConfigExtensions 
    { 
     public static void VerifyAutoMapperConfig(this IServiceProvider app) 
     { 
      var config = app.RequestService<IMapperConfiguration>(); 
      config.AssertConfigurationIsValid(); 
     } 
    } 
} 
+0

おかげで、それは本当に有望だった。残念ながら、TypeConverterを使用しようとすると、同じエラーが発生します。「MyConverterには、引数が0のコンストラクタまたはオプションの引数のみが必要です。\ r \ nパラメータ名:type'。 AM 4.2がIServiceProviderリファレンスを使用して以前のリリースで使用されていたものと同じ依存関係を注入するのではないかと思います。 –

+0

私はここに循環依存があると思う。あなたの 'MyConverter'は' IMapperConfiguration'に依存していますが、 'IMapperConfiguration'は' AutoMapperConfig.Configure'の呼び出しの後でしか解決できませんが、configureの中で 'config.AssertConfigurationIsValid();'それが返される前に解決してください。この呼び出しをConfigureメソッドの外に、つまりStartup.csの 'Configure(IServiceProvider app)'メソッド内で移動してみてください。回答を例文 – Tseng

+0

で更新します。残念ながら、これで修正されませんでした。 Btw、コードをデバッグすると、AutomapperConfig.ConfigureメソッドがStartup.csで追加されたサービス構成から直接呼び出されることがわかります。あなたが言及したように、最初の使用まで延期されません。それは私がどこかで何か間違ったことをしたのか疑問に思います。 –

関連する問題