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 (Dependency Injection - DI), bir sınıfın bağımlılıklarını kendi içinde oluşturmak yerine dışarıdan aldığı bir tekniktir. Bu, kodu daha esnek, test edilebilir ve gevşek bağlı (loosely coupled) hale getirir.

DI olmadan, bir sınıf kendi bağımlılıklarını kendisi oluşturur; bu da değiştirmeyi veya test etmeyi zorlaştırır:

public class OrderService
{
    private EmailSender sender = new EmailSender();  // Sıkı sıkıya bağlı
    
    public void PlaceOrder() => sender.Send("Order placed");
}

DI ile bağımlılıklar, yapıcı (constructor) aracılığıyla aktarılır:

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ı bilmez veya umursamaz. Bağımlılık, nesne oluşturulduğunda "enjekte edilir":

IMessageSender emailSender = new EmailSender();
OrderService service = new OrderService(emailSender);
service.PlaceOrder();  // Email: Sipariş verildi

Bu desen, somut uygulamalar yerine soyutlamalara (arayüzlere) dayanma ilkesini takip eder. Bu, onları kullanan sınıfı değiştirmeden uygulamaların yer değiştirilmesine olanak tanır; bu da birim testi ve esnek mimarilerin sürdürülmesi için gereklidir.

challenge icon

Görev

Kolay

Bağımlılık enjeksiyonunun (dependency injection) gücünü gösteren bir günlükleme (logging) sistemi oluşturalım. Günlüklerin nasıl yazılacağını sabit olarak kodlamak yerine, ayrıntıları bilmeden konsol, dosya simülasyonu veya başka herhangi bir günlükleme hedefiyle çalışabilen esnek bir Logger sınıfı oluşturacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • ILogWriter.cs: Logging ad alanında (namespace) ILogWriter adında bir arayüz (interface) tanımlayın. Bu arayüz, herhangi bir günlükleme hedefi için sözleşmeyi temsil eder ve mesajın nereye yazıldığını açıklayan bir dize (string) döndüren tek bir Write(string message) metoduna sahip olmalıdır.
  • LogWriters.cs: Logging ad alanında ILogWriter arayüzünün iki somut uygulamasını oluşturun:
    • ConsoleLogWriter - Write metodu "Console: " + message döndürür.
    • FileLogWriter - yapıcı metodu (constructor) aracılığıyla bir dosya adı alır ve Write metodu "File[" + filename + "]: " + message döndürür.
  • Logger.cs: Logging ad alanında, bağımlılığını yapıcı metot enjeksiyonu (constructor injection) yoluyla alan bir Logger sınıfı oluşturun. Logger şunları yapmalıdır:
    • Yapıcı metodu aracılığıyla bir ILogWriter kabul etmeli ve bunu özel (private) bir alanda saklamalıdır.
    • Enjekte edilen yazıcıya (writer) yetki veren ve sonucu döndüren bir Log(string message) metoduna sahip olmalıdır.
  • Program.cs: Biri ConsoleLogWriter, diğeri FileLogWriter ile olmak üzere iki farklı günlükçü (logger) oluşturarak bağımlılık enjeksiyonunu gösterin. Aynı Logger sınıfının, hangi bağımlılığın enjekte edildiğine bağlı olarak nasıl farklı davrandığını gösterin.

İki girdi alacaksınız:

  • Dosya günlükçüsü için dosya adı
  • Günlüklenecek mesaj

Bir ConsoleLogWriter ile bir Logger oluşturun ve mesajı günlüğe kaydedin. Ardından (girdiden gelen dosya adını kullanarak) bir FileLogWriter ile başka bir Logger oluşturun ve aynı mesajı günlüğe kaydedin. Her sonucu kendi satırında yazdırın.

Ö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ç değişmediğine dikkat edin; herhangi bir ILogWriter uygulamasıyla çalışır. Bağımlılık enjeksiyonunun özü budur: Logger bir soyutlamaya (arayüze) bağlıdır ve somut uygulama dışarıdan "enjekte edilir". Daha sonra Logger sınıfını hiç değiştirmeden kolayca bir DatabaseLogWriter veya CloudLogWriter ekleyebilirsiniz!

Kopya kağıdı

Bağımlılık Enjeksiyonu (Dependency Injection - DI), bir sınıfın bağımlılıklarını kendisi oluşturmak yerine dışarıdan aldığı, kodun daha esnek, test edilebilir ve gevşek bağlı (loosely coupled) olmasını sağlayan bir tekniktir.

DI olmadan (sıkı bağlı):

public class OrderService
{
    private EmailSender sender = new EmailSender();  // Sıkı bağlı
    
    public void PlaceOrder() => sender.Send("Order placed");
}

DI ile (gevşek bağlı):

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");
}

Bağımlılığı enjekte etme:

IMessageSender emailSender = new EmailSender();
OrderService service = new OrderService(emailSender);
service.PlaceOrder();  // Email: Order placed

DI, somut uygulamalar yerine soyutlamalara (arayüzlere) dayanma ilkesini izleyerek, kullanan sınıfı değiştirmeden uygulamaların yer değiştirilmesine olanak tanır.

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: Bir ConsoleLogWriter ile bir Logger oluşturun ve mesajı günlüğe kaydedin
        // Sonucu yazdırın

        // TODO: Bir FileLogWriter (dosya adını kullanarak) ile başka bir Logger oluşturun ve aynı mesajı günlüğe kaydedin
        // Sonucu yazdırın
    }
}
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