Asp.Net Core Uygulamalarında Farklı DI/IoC Containerlar Nasıl Kullanılır, Autofac Kullanımı

Asp.net core default olarak oldukça lightweight bir sürüm olan built-in dependency injection tool'ı ile birlikte gelmekte ve bu di tool'ını kullanarak basit bir şekilde uygulama genelindeki instance yönetimini sağlayabilmekteyiz. Şu yazımızda built-in DI container nedir nasıl kullanılır değinmiştik. Bununla birlikte asp.net core third-party dependency injection tool'larını da desteklemekte.

Bu yazımızda bir asp.net core uygulamasına Autofac kütüphanesini default DI container'ı olarak nasıl implement ederiz inceleyeceğiz.

Yazımızın başındada bahsettiğimiz gibi asp.net core default built-in DI Container desteği sunmakta ve kullanım olarakta aşağıdaki gibi bağımlılıkları register edebilmekteyiz.

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ICustomerRepository, CustomerRepository);

    services.AddMvc();
}

Ihtiyaç duyduğumuz yerde de bu bağımlılığı constructor injection yöntemiyle inject edip kullanabilmekteyiz.

public class CustomerController : Controller
{
    private readonly ICustomerRepository _customerRepository;

    public HomeController(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }
}

Aynı bu bağımlılıkları autofac, NInject, Unity StructureMap gibi birçok DI Container kütüphanesini kullanarakta tanımlayabiliriz. Bütün bu DI Container'ların instance yönetimi dışında developer'lar tarafından sevilen ve beğenilen bir çok farklı özellikleri bulunmakta. Bunu sağlayan şey ise IServiceProvider interface'i. Asp.Net Core yumlu DI kütüphaneleri bu interface'i implement edip bağımlılıkları bu ortak interface üzerine inşa ettiklerinden asp.net core uygulamalarında third-party DI kütüphanelerini kullanabilmekteyiz. Uygulamaya third-party DI kütüphanesini belirttiğimiz yer ise Startup.cs içerisinde yer alan void ConfigureServices metodunu aşağıdaki gibi IServiceProvider return edecek şekilde değiştirmek.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
   // add services
   
   // return third-party tool's class which is implemented IServiceProvider
}

Bizde örnek olarak Autofac DI Container kütüphanesini projemize implement edip bağımlılıkları bunun üzerinden register edicez. Projemize nuget üzerinden Autofac kütüphanesini install ettiğimizi varsayalım ve autofac builder işlemlerini ConfigureServices metodu içerisinde aşağıki gibi tanımlayalım.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    var builder = new ContainerBuilder();
	
    builder.RegisterType<CustomerRepository>().As<ICustomerRepository>();
	
    builder.Populate(services);
 
    var appContainer = builder.Build();
 
    return new AutofacServiceProvider(appContainer);
}

Kullanım basit haliyle yukarıdaki gibi Builder oluşturup bağımlılıkları register edip sonrasında IServiceProvider interface'ini implement eden AutofacServiceProbider sınıfını return ettik ve artık uygulamamız için DI Container built-in container yerine Autofac olarak implement ettik. 

Autofac dışında diğer DI Container tool'larını kullanmak isterseniz aynen yukarıdaki gibi Startup.cs içerisinde ConfigureService metodunu kullandığınız DI tool'un da yer alan IServiceProvider interface'ini implement eden sınıfı  bağımlılıkları register ettikten sonra return etmeniz yeterli olacaktır.

Comments (5) -

  • Makaleniz için teşekkür ederim. Size bir soru sormak istiyorum.

    Autofac modullerimizi register ettikten sonra constructor injection kullanarak değil de bir metot içerisinde resolve işlemi nasıl yapılır ?

    • Değerli yorumun için teşekkürler. Tabiki mümkün,
      Autofac kütüphanesi içerisindeki IContainer interface'inin Resolve<> extension metodunu kullanarak resolve edebilirsin.
      Örnek kullanım;   ...Container.Resolve<ICustomerRepository>()
      • Asp.net core 3.1 projesinde program.cs içerisinde böyle bir yapılandırma yaptım.

        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                        .ConfigureContainer<ContainerBuilder>(builder =>
                        {
                            builder.RegisterModule(new BusinessModule());
                        })

        Fakat sizin dediğiniz gibi IContainer interface'inin Resolve extension metodu yok. İlgili metot içerisinde
        var repository = Container.Resolve<ICustomerRepository>();
        gibi birşey yapmaya çalışıyorum ama o sınıfların direkt olarak kullanılabilecek bir extension metodu göremiyorum.
        Nerede yanlış yapıyorum anlayamadım Smile


        • Şöyle yapabilirsiniz;
          RegisterModule işlemlerini bir bootstrapper sınıfı içerisine alıp ilgili registration işlemlerini orda yapabilirsiniz. Örnek olarak verecek olursak;


          public static class Bootstrapper
          {
              public static IContainer Container { get; private set; }
              public static AutofacServiceProvider InitializeContainer(IServiceCollection services )
              {
                  var builder = new ContainerBuilder();
                  builder.RegisterModule(new BusinessModule());

                  Container = builder.Build();

                  return new AutofacServiceProvider(Container);
              }
          }

          Sonrasında InitializeContainer metodunu Startup.cs içerisinde ConfigureServices metodunda aşağıdaki gibi call edebilirsin.

          public IServiceProvider ConfigureServices(IServiceCollection services)
          {
              return Bootstrapper.InitializeContainer(services);
          }


          Artık dilediğin yerde  Bootstrapper.Container.Resolve<ICustomerService>(); vs gibi resolve işlemlerini yapabilirsin. IContainer interface'i Autofac kütüphanesi içerisinde bulunan bir interface.

Add comment