Menu
Coddy logo textTech

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ş verildi

Bu 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.

challenge icon

Görev

Kolay

Bağı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: ILogWriter ad alanında Logging adlı 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 bir Write(string message) yöntemine sahip olmalıdır.
  • LogWriters.cs: ILogWriter ad alanında Logging için iki somut uygulama oluştur:
    • ConsoleLogWriter - Write yöntemi Console: {message} döndürür
    • FileLogWriter - oluşturucusu aracılığıyla bir dosya adı alır ve Write yöntemi File[{filename}]: {message} döndürür
  • Logger.cs: Logger ad alanında, bağımlılığını oluşturucu enjeksiyonu aracılığıyla alan bir Logging sınıfı oluştur. Logger şunları yapmalıdır:
    • Oluşturucusu aracılığıyla bir ILogWriter kabul 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ı
  • Program.cs: Biri ConsoleLogWriter, diğeri FileLogWriter kullanan iki farklı günlük kaydedici oluşturarak bağımlılık enjeksiyonunu göster. Aynı Logger sı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 started

Logger 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
    }
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online C# derleyicisi