.Net Core projelerinde dependency injection uygularken eğer built-in container'ı kullanıyorsanız ve onlarca Service,Repository veyahut manager vb. interface/implementasyon'u varsa bunları container'a register etmek biraz uğraştırıyor. Sebebi ise castleWindsor veya Autofac gibi DI Tool'larından alışkın olduğumuz register-all-at-once gibi bir özelliği şuan için bulunmamakta. Yani aşağıdaki gibi her bir isterface ve onun implementasyonu için ayrı ayrı registration tanımlanması gerekmekte.
services.AddSingleton<IUserService, UserService>();
services.AddSingleton<ICustomerService, CustomerService>();
services.AddSingleton<IProductService, ProductService>();
services.AddSingleton<IEmployeeService, EmployeeService>();
services.AddTransient<IUserManager, UserManager>();
services.AddTransient<ICustomerManager, CustomerManager>();
services.AddTransient<IProductManager, ProductManager>();
services.AddTransient<IEmployeeManager, EmployeeManager>();
...
Ancak kısa süre önce github'da paylaşılan ve nuget üzerinden de install edilebilen bir kütüphane yayınlandı.
Scrutor
Scrutor "Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection" şeklinde tanımlanmakta ve bu kütüphane ile aynısı olmasada CastleWindsor ve Autofac de olduğu gibi registration işlemleri biraz olsun basitleşiyor. Scrutor'u projenize install ettikten sonra registration tanımlarken belirttiğiniz interface'in bulunduğu bütün assembly'leri scan edip bağımlılıkları inject etmekte.
Yukarıda built-in container kullanarak register ettiğimiz bağımlılıkları scrutor kullanarak aşağıdaki gibi de yapabiliriz.
services.Scan(scan => scan
.FromAssemblyOf<IAssemblyMarker>()
// ISingletonLifetime adında bir interface tanımlayıp container'a single instance olarak register olmasını istediğimiz dependency'leri bu interface'den inherit ederek doğrudan register edebilmekteyiz.
.AddClasses(classes => classes.AssignableTo<ISingletonLifetime>())
.AsImplementedInterfaces()
.WithSingletonLifetime()
// ITransientLifetime adında bir interface tanımlayıp container'a transientLifeTime'ına sahip olmasını istediğimiz dependency'leri bu interface'den inherit ederek doğrudan register edebilmekteyiz.
.AddClasses(classes => classes.AssignableTo<ITransientLifetime>())
.AsImplementedInterfaces()
.WithTransientLifetime());
public interface ISingletonLifetime
{ }
public interface ITransientLifetime
{ }
public interface ICustomerService : ISingletonLifetime
{
//todo
}
public interface ICustomerManager : ITransientLifetime
{
//todo
}
Scrutor startUp anında assembly'i scan edip ITransientLifetime ve ISingletonLifetime interface'lerini ve onların implementedInterface'lerini bularak implementasyonlarını doğrudan container'a register eder.
Scrutor doğru kullanıldığı takdirde oldukça başarılı bir kütüphanedir ve bizleri dependecny injection konusunda belli başlı bazı zorluklardan kurtarabilmektedir.