Selamlar ,
Bir önceki yazımda .Net framework ile birlikte gelen DI kütüphanesindeki servis ömür’lerini incelemiştik. Varsayılanın haricinde üçüncü parti uygulamalarla da bunları özelleştirebileceğimizden bahsetmiştik. Bu yazımda harici bir paket olan Autofac kullanımından bahsedeceğim. Varsayılanın aksine Dependency sınıflarımızı nasıl yönetebiliriz bunlar hakkında konuşacağız.
Autofac Nedir ?
Yalın bir tabirle ifade edecek olursak , .NET tabanlı framework için geliştirilmiş IOC (Inversion Of Control) container’dır. Sınıflar birbirleriyle etkileşime girdiğinde , boyut ve karmaşıklık bakımından büyüdükçe uygulamaların daha esnek kalması için aralarındaki bağımlılıkları yönetir. Sadece bağımlılıkları yönetmekle kalmaz uygulamalarımızı modüler bir yapıya dönüştürmek için de oldukça faydalı kendisi.
Bağımlılıkları yönetmek için varsayılan DI kütüphanesinin neyi eksik diyebilirsiniz 🙂
Kısaca buna da değinelim ;
.Net framework ile gelen DI, işlevsellik sağlasa da çeşitli sınırlamaları da beraberinde getirir. Autofac ile bu sınırları aşıp uygulamamızı daha esnek hale getirebiliriz. Bunu daha iyi açıklamamız için kısaca Aspect Oriented Programming konusuna değinmemiz gerekiyor.
AOP çok detaylı ve üzerinde durulması gereken konulardan biri. Genellikle yazılım şirketlerinde mimari departmanının üzerinde kafa yorduğu bir başlık. Çok fazla detaya girmeden yüzeysel olarak ifade etmeye çalışacağım.
Aspect Oriented Programming Nedir ?
Uygulamalarımızda modülerleşmeyi geliştirmek için kesişen ilgileri (Cross-Cutting Concerns) ayırarak Nesneye dayalı programlamayı (OOP) tamamlayan bir programlama paradigmasıdır.
Nedir bu kesişen ilgiler ?
Projemiz büyüdükçe birbirini tekrar eden bir çok iş yapma gereksinimimiz ortaya çıkmaktadır. OOP bu konuda bize yardımcı olsa da AOP projemizi daha yalın ve modüler hale getirmeyi, mevcut durumda Readability, Reusability,Extensibility kavramlarını çok daha etkili kullanmamızı sağlayacaktır.
Business katmanında sürekli olarak tekrar eden Logging , Authorization , Exception Handling , Cache gibi her aşamada kontrol ettiğimiz durumları modüler yapıya kavuşturup tek yerden yönetilmesini amaçlar.
Kesişen ilgileri birbirinden nasıl ayıracağız ?
Bu noktada devreye Interceptor kavramı giriyor. Metod çağrımları sırasında araya girerek bizlerin kesişen ilgilerimizi işletmemizi ve yönetmemizi sağlamaktadır. Böylece metodların çalışmasından önce veya sonra bazı işlemler (Logging , Cache vs.) gerçekleştirebilmekteyiz. Oluşturduğumuz bu yapıları attribute olarak kullanabiliriz.
Autofac , hem bağımlılıklarımızı yöneten hem de AOP’u destekleyen ve bu işleri çok efektif bir şekilde yapabilen bir kütüphane olarak karşımıza çıkıyor.
Autofac Implementasyonu
Adımlar
- İlk olarak Nuget Package aracılığıya ilgili paketleri yüklüyoruz.
(Eğer projenizde Interceptor vs kullanmak isterseniz Autofac.Extras.DynamicProxy de indirmeniz gerekiyor.)
2. Program.cs sınıfımızı yapılandırmamız gerekiyor. Autofac.Extensions.DependencyInjection ile birlikte gelen ilgili servis provider’ını ekliyoruz. (AutofacServiceProviderFactory())
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
3. Yapacağımız örnek için ilgili interface’i oluşturuyorum.
public interface IStudentManager
{
bool Add(StudentDTO student);
bool Delete(int id);
bool Update(StudentDTO student);
List<StudentDTO> GetAllStudentList();
}
4. Oluşturduğum interface’e karşılık gelen ilgili concrete class’ı oluşturuyorum.
public class StudentManager : IStudentManager
{
private readonly IStudentDAL _dal;
public StudentManager(IStudentDAL dal)
{
_dal = dal;
}
public bool Add(StudentDTO student)
{
return true;
}
public bool Update(StudentDTO student)
{
return true;
}
public bool Delete(int id)
{
return true;
}
public List<StudentDTO> GetAllStudentList()
{
return _dal.GetAllStudentList();
}
}
5. Servisleri oluşturduktan sonra şimdi de Autofac aracılığıyla bunları kaydetmemiz gerekiyor. Bunun iki yolu var ;
a. Eğer servislerimiz çok fazla değilse Startup.cs içinde yönetebiliriz.
İlk olarak Startup.cs içinde servisleri nasıl kaydediyoruz onu inceleyelim.
public class Startup
{
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<StudentManager>().As<IStudentManager>().InstancePerDependency();
}
}
StudentManager servisimizi ContainerBuilder yardımıyla Startup.cs sınıfı içinde Register edebiliriz. ( InstancePerDependency ← → Transient )
Eklediğimiz ConfigureContainer metodu , ConfigureService metodundan sonra çalışır.
b. Uygulamamızda çok fazla servis olacaksa bunu ayrı bir modül de yönetmemiz daha doğru olacaktır.
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<StudentManager>().As<IStudentManager>();
// Other Lifetime
// Transient
//builder.RegisterType<EmployeeService>().As<IEmployeeService>()
// .InstancePerDependency();
//// Scoped
//builder.RegisterType<StudentManager>().As<IStudentManager>()
// .InstancePerLifetimeScope();
//// Singleton
//builder.RegisterType<EmployeeService>().As<IEmployeeService>()
// .SingleInstance();
}
Ayrı bir RegisterModule sınıfı oluşturuyorum. Autofac ile gelen Module sınıfı bize çeşitli override metodlar sunuyor. Varsayılan .Net Framework ile birlikte gelen servis ömürlerini (dependency lifetimes) de istersem kullanabilirim. StudentManager servisimin register işlemini tamamladım.
6. Şimdi Startup.cs sınıfında bu modülü register etmem gerekiyor.
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new RegisterModule());
}
Servislerimiz inject edilmeye hazır hale geldi. İlgili Controller’da inject işlemini gerçekleştirebilirim.
public class HomeController : Controller
{
private readonly IStudentManager _manager;
public HomeController(IStudentManager manager)
{
_manager = manager;
}
public IActionResult DeleteStudent()
{
bool sonuc = _manager.Sil(1);
return Ok(sonuc);
}
}
Bitirirken
Autofac’in sağladığı modüler yapı ve kısıtlayıcılığının minimum olması büyük projelerin içinde bir nevi harita işlevi görüyor. “Clean Code” kapsamında Startup sınıfını servislerle doldurmamış ve paket içinde gelen diğer fonksiyonaliteleri de kullanma imkanına sahip oluyoruz.
Umarım faydalı olmuştur.
Bir başka konuda görüşmek üzere…
Kaynaklar
Dependency Injection and Inversion of Control on .Net Core
Do you know about the terms Dependency Inject and/or Inversion of Control? No? Let’s go to talk about it! I’ll explain…
alexalvess.medium.com
Autofac with ASP.NET Core
How is Autofac more flexible than a built-in dependency injection framework in ASP.NET Core?
enlear.academy