.Net Core公式DIフレームワーク

6022 ワード

NetCoreは方法のDIフレームワークを提供し,AspNetCoreでこの注入フレームワークを大量に使用した.拡張パッケージとして提供するもので、使用時にはNugetパッケージでMicrosoft.Extensions.DependencyInjectionで使用します.他のDIフレームワークと比較して軽量であり、コンストラクタ注入のみをサポートし、属性注入、およびメソッド注入はサポートされていない.
使用は簡単ですが、一般的な手順は次のとおりです.
// 1.     
var serviceCollection = new ServiceCollection();
   .AddSingleton()
   .AddTransient()
   .BuildServiceProvider())

// 2.        
ServiceProvider serviceProvider serviceCollection.BuildServiceProvider();

// 3.             Provider.GetService()       
var IFoo = serviceProvider.GetService();

サービスの登録方法
サービスには一般的に以下の方法があります.
  • serviceCollection.Add(ServiceDescriptor item)
  • serviceCollection.AddXXX()
  • serviceCollection.AddXXX(Func implementationFactory)

  • 次の文は同じです.
    serviceCollection.AddTransient();
    serviceCollection.Add(new ServiceDescriptor(typeof(IFoo),typeof(Foo), ServiceLifetime.Transient));
    serviceCollection.AddTransient(provider => new Foo());
    

    サービスプロバイダサービスプロバイダ
    サービスインスタンスの作成、破棄はServiceProviderが管理します.生成されたサービスインスタンスは、サービスインスタンスが他の場所で使用される可能性があるため、オブジェクトのDisposeメソッドを実行しないのが一般的です.
    ServiceProviderを解放すると、生成されたオブジェクトが解放されます.
    インスタンスを生成するとき、オブジェクトがDisposeインタフェースを実装すると、そのオブジェクトは_に保存されます.disposablesリストでは、Providerが解放されると自動的に_が呼び出されます.disposables要素オブジェクトのDisposeメソッド
    ServiceProvider自体が新しいServiceProviderを作成することで、役割ドメインScopeが生成されます.
    サービスのライフサイクル
    ライフサイクルは3つに分けられます.
  • 過渡Transient:サービスプロバイダから取得するたびに、新しいインスタンスが返されます.
  • 役割ドメインScope:同じ役割ドメインで生成するインスタンスは同じ、すなわち同じServiceProviderで取得したインスタンスは同じ
  • である.
  • 単例Singleton:いずれかのServiceProviderで取得した例は同じ
  • である.
    役割ドメインは、主に特定のServiceProvider、すなわち同一のServiceProviderの下でScopeタイプとして登録されているオブジェクトが一例である
    using (ServiceProvider rootProvider = new ServiceCollection()
       .AddTransient()
       .AddScope()
       .AddSingleton()
       .BuildServiceProvider())
    {
        IFoo foo = rootProvider.GetService();
        IFoo foo2 = rootProvider.GetService();
    
        IBar bar = rootProvider.GetService();
        IBar bar2 = rootProvider.GetService();
    
        IFoobar foobar = rootProvider.GetService();
        IFoobar foobar2 = rootProvider.GetService();
    
        IFoo foo3 = null;
        IBar bar3 = null;
        IFoobar foobar3 = null;
        using(var scope = rootProvider.CreateScope())
        {
            var childProvider = scope.ServiceProvider;
            foo3 = childProvider.GetService();
            bar3 = childProvider.GetService();
            foobar3 = childProvider.GetService();
        }
    
        var childProvider2 = rootProvider.CreateScope().ServiceProvider;
        IFoo foo3 = childProvider2.GetService();
        
        //    1
    }
    
    //    2
    

    インスタンスオブジェクトの説明
  • IFOoがTransientに登録するとfoo foo 2,foo 3はいずれも
  • を待たない.
  • IBarがScopeとして登録されている場合、bar=bar 2(同じrootProviderで提供されているため)、bar 2<>bar 2(異なるProviderで提供されているため、1つはrootProviderで、1つはchildProviderであるため)
  • IoobarはSingletonに登録されているのでfoobar==foobar 2==foobar 3
  • インスタンスの解放タイミング
  • が【実行ポイント1】まで実行された場合、解放:
  • childProvider自体は、childProviderが作成したbar 3、foo 3
  • を再解放する.
  • bar3
  • foo3

  • が【実行ポイント2】まで実行された場合、解放:
  • rootProvider自体
  • foo
  • foo2
  • bar、(bar 2はありません.bar 2はbarですから)
  • childProvider 2、およびchildProvider 2によって作成するfoo 3

  • ASP.Net Coreでの使用
    asp.Netcoreには主に2つのServiceProviderがあり、対応するサービスインスタンスを手動で取得できます.
  • WebHostのServiceProvider、すなわちwebHost.Services
  • Http要求におけるHttpContextのServiceProvider、すなわちHttpContext.RequestServices

  • これらの関係は親子関係である:Http要求におけるServiceProviderは、WebHostのServiceProviderに従ってミドルウェアRequestServicesContainerMiddlewareによって生成される.
    Httpリクエストが終了すると、HttpリクエストのServiceProviderが解放され、その役割ドメインのインスタンスオブジェクトが解放されます.
    ちゅうにゅうモード
    public class SampleController ControllerBase
    {
        // 1.   :      
        private IService _service = null;
        public SampleController(IService service)
        {
            this._service = service;
        }
    
        // 2.   :      
        [HttpPost]
        public IActionResult Method1([FromServices] IService service) => service.DoSomething()
        
        // 3.   :  HttpContext,    
        [HttpGet]
        public IActionResult Method2() 
        {
            IService service = HttpContext.RequestServices.GetService<>(IService);
            ...
        }
        ...
    }
    

    他の3番目に成熟したIocフレームワークを使用する(推奨しない)
    公式DIフレームワークは他の成熟したIocフレームワークに取って代わることができるが、NetCore DIフレームワークは「パッケージング」として、他のDIフレームワーク(例えばAutofac、Unityなど)を挿入して他のDIフレームワークを挿入する目的で、主に他のフレームワークのいくつかの利点、例えば一括登録、属性注入などを利用したいと考えています.
    置き換えの方法は,主にサービスメソッドConfigureServicesを再登録する際に,サードパーティDI拡張実装のIServiceProviderで公式DIのIServiceProviderを置き換えている.
    現在、公式DI拡張を実現しているサードパーティ製フレームワークは、AspectCore、Autofac、Unityであり、サードパーティ製DIフレームワークの使用は若干の利便性をもたらしているが、サードパーティ製DI容器の特性への依存性をもたらしている
    Asp.NetCoreでのAutofacの使用
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
         services.AddApplicationInsightsTelemetry(Configuration);
         services.AddMvc();
         return RegisterAutofac(services);
    }
    
    private IServiceProvider RegisterAutofac(IServiceCollection services)
    {
         var builder = new ContainerBuilder();
         builder.Populate(services);
         var assembly = this.GetType().GetTypeInfo().Assembly;
         builder.RegisterType();
         builder.RegisterAssemblyTypes(assembly)
                      .Where(type =>
                       typeof(IDependency).IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract)
                      .AsImplementedInterfaces()
                      .InstancePerLifetimeScope().EnableInterfaceInterceptors().InterceptedBy(typeof(AopInterceptor));
          this.ApplicationContainer = builder.Build();
          return new AutofacServiceProvider(this.ApplicationContainer);
    }