C# 'ta Dependency Injection, özellikle daha karmaşık ASP.NET Core uygulamalarında bağımlılıkları organize ederken hayat kurtarıcıdır. IServiceCollection'a zaten aşinaysanız veya halihazırda sağlanan DI tekliflerine mümkün olduğunca yakın kalmak istiyorsanız, C#'taki Scrutor harika bir geliştirmedir.
Bu yazıda size C#'ta Dependency Injection ve Scrutor'a üst düzey bir genel bakış sunacağım. Ancak buradan itibaren, Scrutor ile kullanabileceğiniz ve başvurunuzda çok faydalı olabilecek 3 ipucuna geçiyoruz!
Scrutor, C# dilinde bağımlılık enjeksiyonunu geliştiren güçlü bir NuGet paketidir. Bağımlılıkların kaydedilmesini ve çözümlenmesini basitleştirerek kodunuzu yönetmenizi ve düzenlemenizi kolaylaştırır.
Bağımlılık enjeksiyonu, gevşek birleştirmeyi teşvik eden ve test edilebilirliği ve sürdürülebilirliği geliştiren uygulamaları yapılandırmaya yönelik popüler bir yaklaşımdır. Bağımlılıkları doğrudan sınıf içinde oluşturmak yerine, sınıfa enjekte etmeyi içerir. Bu, bağımlılığı yaratma sorumluluğunun onu gerektiren sınıfa ait olmadığı, bunun yerine çağrı yığınındaki bir kişiye ait olduğu anlamına gelir. Sonuçta bu, neredeyse tüm bağımlılık oluşumunu uygulamanın giriş noktasına iter ve uygulamayı kullanışsız hale getirir. Ancak bağımlılık enjeksiyon çerçeveleri tüm bu mantığın temizlenmesine ve düzenlenmesine yardımcı olur.
Scrutor, bağımlılıkları kaydetmek ve çözmek için basit ve sezgisel bir yol sağlayarak bu konsepti bir adım daha ileriye taşıyor. Scrutor ile artık her bağımlılığı tek tek manuel olarak kaydetmenize gerek yok. Bunun yerine süreci otomatikleştirmek için kuralları ve nitelikleri kullanabilirsiniz.
Kayıt ve çözümleme için Scrutor'un C#'ta nasıl kullanılacağını göstermek için basit bir senaryoyu ele alalım. UserRepository ve ProductRepostiory gibi farklı veri havuzlarının kullanımını gerektiren bir uygulamamız olduğunu düşünün.
Öncelikle projemize Scrutor NuGet paketini kurmamız gerekiyor. Paket Yönetici Konsolunu açın ve aşağıdaki komutu çalıştırın:
Install-Package Scrutor
Daha sonra depolarımızı ve bunlara karşılık gelen arayüzleri tanımlamamız gerekiyor. Bu örnek aslında boş, ancak birazdan bunlara değineceğiz:
public interface IUserRepository { // Interface methods } public class UserRepository : IUserRepository { // Implementation } public interface IProductRepository { // Interface methods } public class ProductRepository : IProductRepository { // Implementation }
Şimdi Scrutor'u kullanarak bağımlılıklarımızı bağlayalım. Başlangıç kodunuza (ASP.NET Core'daki ConfigurationServices yönteminde olduğu gibi) aşağıdaki kodu ekleyin:
services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.AssignableToAny( typeof(IUserRepository), typeof(IProductRepository))) .AsImplementedInterfaces() .WithScopedLifetime());
Bu kod, Startup sınıfını içeren derlemeyi taramak için Scrutor'un Tarama yöntemini kullanır. Daha sonra IUserRepository veya IProductRepository arayüzlerine atanabilen sınıfları filtreler. Son olarak bu arayüzlerin uygulamalarını haritalandırır ve bunları ilgili arayüzlere kaydeder.
Artık bu bağımlılıkları sınıflarımıza enjekte edebiliriz. Örneğin, IUserRepository gerektiren bir UserService sınıfımız olduğunu varsayalım:
public class UserService { private readonly IUserRepository _userRepository; public UserService(IUserRepository userRepository) { _userRepository = userRepository; } // Rest of the class implementation }
IUserRepository'yi yapıcıda bir bağımlılık olarak bildirerek Scrutor, IServiceCollection ile birlikte UserRepository örneğini bizim için otomatik olarak çözecek ve enjekte edecektir.
Bir IService
hizmet arayüzünüz ve bir MyService
uygulamanız olduğunu hayal edin. MyService
her yöntem çağrısının giriş ve çıkışını, iş mantığını günlüğe kaydetme endişeleriyle kirletmeden günlüğe kaydetmek istiyorsunuz.
İlk olarak IService
arayüzünü ve uygulamasını tanımlayın:
public interface IService { void DoWork(); } public class MyService : IService { public void DoWork() { // Business logic here } }
Daha sonra, IService
uygulayan bir dekoratör sınıfı LoggingDecorator
oluşturun. Bu sınıf, asıl hizmeti saracak ve devredilen yöntem çağrılarının etrafına günlük kaydı ekleyecektir:
public class LoggingDecorator : IService { private readonly IService _decorated; private readonly ILogger<LoggingDecorator> _logger; public LoggingDecorator(IService decorated, ILogger<LoggingDecorator> logger) { _decorated = decorated; _logger = logger; } public void DoWork() { _logger.LogInformation("Starting work."); _decorated.DoWork(); _logger.LogInformation("Finished work."); } }
Şimdi hizmetinizi ve dekoratörünü Startup.cs
veya hizmetlerinizi yapılandırdığınız her yere kaydetmek için Scrutor'u kullanın:
public void ConfigureServices(IServiceCollection services) { // Register the base service services.AddScoped<IService, MyService>(); // Use Scrutor to apply the decorator services.Decorate<IService, LoggingDecorator>(); // Make sure to register the ILogger or ILogger<T> dependencies if not already done }
Bu kurulum, IService
kaydını LoggingDecorator
ile sarmak için Scrutor'u kullanır. IService
çözümlenirken, DI kapsayıcısı LoggingDecorator
örneğini sağlayacak ve bu da MyService
örneğini saracaktır. Bu yaklaşım, günlüğe kaydetme mantığını iş mantığınızın dışında tutarak endişelerin ayrılmasını sağlar.
Karmaşık sistemler oluşturduğumuzda, özellik bayrakları gibi bir şeyi tanıtmak istediğimiz durumlar sıklıkla olur. Bunlar, yapılandırmaya bağlı olarak farklı kod yolları kullanmamıza olanak tanır ve uygulamanın tamamını yeniden derleyip dağıtmamıza gerek kalmaz. Bazı durumlarda, bu sadece farklı bir kod yolu seçmekle ilgili değil, bir şeyin tüm uygulamasının değiştirilmesiyle de ilgili!
Gelin birlikte bir örnek deneyelim! Birden çok uygulamaya sahip bir IFeatureService
arayüzünüz olduğunu varsayalım: NewFeatureService
(yeni, deneysel bir özellik) ve StandardFeatureService
(mevcut, kararlı özellik). Bir yapılandırma bayrağına göre çalışma zamanında bu uygulamalar arasında geçiş yapmak istiyorsunuz.
İlk olarak IFeatureService
arayüzünü ve uygulamalarını tanımlayın:
public interface IFeatureService { void ExecuteFeature(); } public class NewFeatureService : IFeatureService { public void ExecuteFeature() { // New feature logic } } public class StandardFeatureService : IFeatureService { public void ExecuteFeature() { // Standard feature logic } }
Daha sonra, özellik değiştirme ayarına göre hangi uygulamanın kullanılacağını belirlemenin bir yoluna ihtiyacınız var. Bu, appsettings.json
dosyasındaki bir değer, bir veritabanı ayarı veya başka herhangi bir yapılandırma kaynağı olabilir.
Şimdi, özellik geçişine dayalı olarak uygun hizmet uygulamasını dinamik olarak kaydetmek için Scrutor'u kullanın:
public void ConfigureServices(IServiceCollection services) { // Assume GetFeatureToggleValue() retrieves the current feature toggle setting var useNewFeature = GetFeatureToggleValue("UseNewFeature"); // Dynamically register the appropriate implementation based on the feature toggle if (useNewFeature) { services.AddScoped<IFeatureService, NewFeatureService>(); } else { services.AddScoped<IFeatureService, StandardFeatureService>(); } // Optional: You could combine this with the previous example // to use the decorator pattern too! // services.Decorate<IFeatureService, FeatureServiceProxy>(); } private bool GetFeatureToggleValue(string featureName) { // This method would typically check your // configuration source to determine if the feature is enabled // For simplicity, this is just a placeholder return false; // or true based on actual configuration }
Bunun gibi bir yaklaşımı benimsemek bize şu konularda yardımcı olabilir:
Bu yazımda sizlere C#'ta Scrutor ile bağımlılık enjeksiyonu için 3 basit ipucu sundum. Bağımlılık enjeksiyonunun ne olduğuna ve Scrutor'un buna nasıl uyduğuna dair kısa bir genel bakışın ardından doğrudan örneklerimize geçtik. Montaj taramasını, bağımlılıkların nasıl dekore edileceğini ve hatta tüm uygulamaları işaretleyen özelliğin nasıl dikkate alınacağını görmemiz gerekiyor!
Bağımlılık enjeksiyonu, uygulamalarınızın karmaşıklığı arttıkça büyük ölçüde basitleştirebilecek bir şeydir ve Microsoft'un yerleşik IServiceCollection teklifine bağlı kalmak istiyorsanız Scrutor size çok yardımcı olabilir. Bunu yararlı bulduysanız ve daha fazla öğrenme fırsatı arıyorsanız, haftalık ücretsiz yazılım mühendisliği bültenime abone olmayı ve YouTube'daki ücretsiz videolarıma göz atmayı düşünün! Discord'da bana ve diğer topluluk üyelerine katılın!