Dependency Injection Temelleri
Coddy'nin C# Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 46 / 70.
Bağımlılık Enjeksiyonu (DI), bir sınıfın bağımlılıklarını kendisinin oluşturmak yerine dışarıdan aldığı bir tekniktir. Bu, kodu daha esnek, test edilebilir ve gevşek bağlı hâle getirir.
DI olmadan, bir sınıf kendi bağımlılıklarını oluşturur; bu da değiştirmeyi veya test etmeyi zorlaştırır:
public class OrderService
{
private EmailSender sender = new EmailSender(); // Sıkı bağlı
public void PlaceOrder() => sender.Send("Order placed");
}DI ile bağımlılıklar kurucu üzerinden geçirilir:
public interface IMessageSender
{
void Send(string message);
}
public class EmailSender : IMessageSender
{
public void Send(string message) => Console.WriteLine("Email: " + message);
}
public class OrderService
{
private IMessageSender sender;
public OrderService(IMessageSender sender)
{
this.sender = sender;
}
public void PlaceOrder() => sender.Send("Order placed");
}Artık OrderService, e-posta, SMS veya test için sahte bir gönderici kullanıp kullanmadığını bilmiyor ve bunu önemsemiyor. Bağımlılık, nesne oluşturulduğunda "enjekte edilir":
IMessageSender emailSender = new EmailSender();
OrderService service = new OrderService(emailSender);
service.PlaceOrder(); // E-posta: Sipariş verildiBu desen, somut uygulamalar yerine soyutlamalara (arayüzlere) bağımlı olma ilkesini izler. Kullanımları sağlayan sınıfı değiştirmeden uygulamaların değiştirilmesine olanak tanır; bu da birim testi yapmak ve esnek mimarileri sürdürmek için gereklidir.
Görev
KolayBağımlılık enjeksiyonunun gücünü gösteren bir günlük kaydı sistemi oluşturalım. Günlüklerin nasıl yazıldığını sabit kodlamak yerine, ayrıntıları bilmeden herhangi bir günlük hedefine (konsol, dosya simülasyonu veya başka herhangi bir şey) uyum sağlayabilen esnek bir Logger sınıfı oluşturacaksın.
Kodunu üç dosyaya ayıracaksın:
ILogWriter.cs:ILogWriterad alanındaLoggingadlı bir arabirim tanımla. Bu arabirim, herhangi bir günlük hedefi için sözleşmeyi temsil eder ve iletinin nereye yazıldığını açıklayan bir dize döndüren tek birWrite(string message)yöntemine sahip olmalıdır.LogWriters.cs:ILogWriterad alanındaLoggingiçin iki somut uygulama oluştur:ConsoleLogWriter-WriteyöntemiConsole: {message}döndürürFileLogWriter- oluşturucusu aracılığıyla bir dosya adı alır veWriteyöntemiFile[{filename}]: {message}döndürür
Logger.cs:Loggerad alanında, bağımlılığını oluşturucu enjeksiyonu aracılığıyla alan birLoggingsınıfı oluştur.Loggerşunları yapmalıdır:- Oluşturucusu aracılığıyla bir
ILogWriterkabul etmeli ve bunu özel bir alanda saklamalı - Enjekte edilen yazıcıya yetki devreden ve sonucu döndüren bir
Log(string message)yöntemine sahip olmalı
- Oluşturucusu aracılığıyla bir
Program.cs: BiriConsoleLogWriter, diğeriFileLogWriterkullanan iki farklı günlük kaydedici oluşturarak bağımlılık enjeksiyonunu göster. AynıLoggersınıfının, hangi bağımlılığın enjekte edildiğine bağlı olarak nasıl farklı davrandığını göster.
İki girdi alacaksın:
- Dosya günlük kaydedicisi için dosya adı
- Günlüğe kaydedilecek ileti
Bir Logger ile bir ConsoleLogWriter oluştur ve iletiyi günlüğe kaydet. Ardından bir Logger ile (girdiden alınan dosya adını kullanarak) başka bir FileLogWriter oluştur ve aynı iletiyi günlüğe kaydet. Her sonucu kendi satırına yazdır.
Örneğin girdiler app.log ve System started ise çıktı şöyle olmalıdır:
Console: System started
File[app.log]: System startedLogger sınıfının hiçbir zaman değişmediğine dikkat et - herhangi bir ILogWriter uygulamasıyla çalışır. Bu, bağımlılık enjeksiyonunun özüdür: Logger bir soyutlamaya (arabirime) bağımlıdır ve somut uygulama dışarıdan "enjekte edilir". Daha sonra DatabaseLogWriter sınıfını hiç değiştirmeden kolayca bir CloudLogWriter veya Logger ekleyebilirsin!
Kendin dene
using System;
using Logging;
class Program
{
public static void Main(string[] args)
{
// Girdileri oku
string filename = Console.ReadLine();
string message = Console.ReadLine();
// TODO: ConsoleLogWriter ile bir Logger oluştur ve mesajı logla
// Sonucu yazdır
// TODO: FileLogWriter ile (filename kullanarak) başka bir Logger oluştur ve aynı mesajı logla
// Sonucu yazdır
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici Dosyalarİsim Alanları ve YönergelerSınıf ve Nesnelere Giriş'this' Anahtar KelimesiMetotlar ve ParametrelerAlanlar ve ÖzelliklerYapıcı MetotlarNesne BaşlatıcılarÖzet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtım (:) Sözdizimi'base' Anahtar KelimesiVirtual ve Override Anahtar KelimeleriSealed Sınıflar'object' Temel SınıfıÖzet - Çalışan Hiyerarşisi7İleri Düzey Özellikler
Operatör Aşırı Yüklemeİndeksleyiciler (this[])ToString() Geçersiz KılmaGenişletme MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişThread-Safe SingletonFactory KalıbıObserver Kalıbı (Olaylar)Strategy Kalıbı2Özellikler ve Statik Üyeler
Otomatik Uygulanan ÖzelliklerSadece Okunur/Yazılır ÖzelliklerStatik Alanlar ve MetotlarStatik Sınıflarİfade Gövdeli Üyeler5Polimorfizm ve Arayüzler
Derleme vs Çalışma Zamanı PolimorfizmiArayüz vs Soyut SınıfÇoklu ArayüzlerBelirgin ArayüzlerUpcasting ve DowncastingÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kalıtım yerine KompozisyonGenerics (Sınıflar ve Metotlar)Delegates ve EventlerAttributes ve ReflectionIDisposable ve using İfadesiDependency Injection Temelleri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit Kalıbı3Sınıf Mimarisi
Örnek vs Statik Veri'readonly' ve 'const' Anahtar KelimeleriDestekleyici Alanlar (Backing Fields)Özet - Banka Hesabı Yöneticisi6Kapsülleme
Erişim BelirleyicilerKapsülleme için ÖzelliklerVeri Gizleme UygulamasıDeğişmezlik KalıplarıÖzet - Öğrenci KayıtlarıKendi başına pratik yap: Online C# derleyicisi