NET Dependency Injection (DI) Nedir ve Nasıl Kullanılır?

NET Dependency Injection (DI) Nedir ve Nasıl Kullanılır?

Blog Bilgileri

  • Yazar: Fatih Kastalmiş
  • E-Posta: fatih.kastalmis@gmail.com
  • Kategori: Yazılım
  • Yayın Tarihi: 02 May 2025

Modern yazılım geliştirme dünyasında, uygulamaların sürdürülebilir, genişletilebilir ve test edilebilir olması birincil önceliktir. Ancak bileşenler doğrudan birbirine bağımlı hale geldiğinde, kodun tekrar kullanılabilirliği düşer, test yazmak zorlaşır ve bakım maliyeti artar. İşte bu noktada Dependency Injection (DI) devreye girer.

Dependency Injection, bir sınıfın ihtiyaç duyduğu bağımlılıkları (örneğin başka sınıflar, servisler) doğrudan kendisi oluşturmadan, dışarıdan almasını sağlayan bir tasarım desenidir. Bu sayede, sınıflar birbirine doğrudan bağımlı olmaz; sadece arayüzlere bağımlı hale gelirler. Böylece uygulamanızda gevşek bağlılık (loose coupling) sağlanır.

.NET Core ve devam eden sürümler, Dependency Injection yerleşik olarak destekler. Framework bize bu bağımlılıkları programatik olarak yönetme, yaşam döngüsünü belirleme ve servisleri enjekte etme imkânı sunar.


Temiz Mimarinin Temeli Dependency Injection

Dependency Injection Neden Kullanılır?

  1. Kodun gevşek bağlı (loosely coupled) olmasını sağlar.
  2. Test süreçlerinde mock servislerin kullanılmasını mümkün kılar.
  3. Tek sorumluluk ilkesi (SRP) uygulanabilir hale gelir.
  4. Uygulama daha esnek ve bakımı kolay olur.

Kötü Örnek: Doğrudan Bağımlılık Oluşturma

public class NotificationManager
{
private EmailService _emailService = new EmailService();

public void Notify(string message)
{
_emailService.SendEmail(message);
}
}

🔴 Sorunlar:

  1. NotificationManager sadece EmailService ile çalışabilir.
  2. EmailService değişirse NotificationManager da değişmek zorundadır.
  3. Test etmek zordur çünkü sahte bir servis verilemez.

Doğru Örnek: Interface + DI Yaklaşımı

public interface IMessageService
{
void SendMessage(string message);
}

public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Email: {message}");
}
}

public class NotificationManager
{
private readonly IMessageService _messageService;

public NotificationManager(IMessageService messageService)
{
_messageService = messageService;
}

public void Notify(string message)
{
_messageService.SendMessage(message);
}
}

✅ Artık NotificationManager sadece IMessageService bağlıdır. Bu sayede farklı servislerle de çalışabiliriz:

public class SmsService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"SMS: {message}");
}
}

.NET Core Dependency Injection(DI) Kaydı ve Kullanımı

builder.Services.AddScoped<IMessageService, EmailService>();
builder.Services.AddScoped<NotificationManager>();

var app = builder.Build();

var notifier = app.Services.GetRequiredService<NotificationManager>();
notifier.Notify("Merhaba Dependency Injection!");

AddScoped vs AddSingleton vs AddTransient

AddSingleton: Uygulama süresince tek örnek. Genellikle log, cache gibi global veriler için uygundur.
AddScoped: Her HTTP isteğinde bir örnek. Web API projelerinde en yaygın tercih edilen yöntemdir.
AddTransient: Her kullanımda yeni bir örnek. Hafif, bağımsız servisler için idealdir.

Unit Test ile DI Kullanımı

Mock servisle test kolaylığı:

public class FakeMessageService : IMessageService
{
public string SentMessage { get; private set; }

public void SendMessage(string message)
{
SentMessage = message;
}
}

[Test]
public void Notify_ShouldCallSendMessage()
{
var fakeService = new FakeMessageService();
var manager = new NotificationManager(fakeService);
manager.Notify("Test mesajı");

Assert.AreEqual("Test mesajı", fakeService.SentMessage);
}

Gerçek Hayattan Senaryo: Logger Örneği

public interface ILoggerService
{
void Log(string message);
}

public class ConsoleLogger : ILoggerService
{
public void Log(string message)
{
Console.WriteLine($"[LOG] {message}");
}
}

public class ProductService
{
private readonly ILoggerService _logger;

public ProductService(ILoggerService logger)
{
_logger = logger;
}

public void AddProduct(string name)
{
_logger.Log($"Product added: {name}");
}
}

🧠 Özetle:

Dependency Injection, .NET projelerinde esneklik, test edilebilirlik ve bakım kolaylığı sağlar. 🎯 Kodların sıkı sıkıya birbirine bağlı olmasını önleyerek, daha sürdürülebilir ve modüler bir yapı oluşturur.

👨‍🔧 Mock servislerle test süreci kolaylaşır, 🧪 farklı senaryolar denenebilir.

📦 AddScoped, AddSingleton ve AddTransient gibi yaşam süresi seçenekleriyle servislerin kullanım biçimi tamamen kontrol altına alınabilir.

🔧 Gerçek dünyada logger, email, sms, database gibi servislerin yönetiminde DI büyük kolaylık sağlar.

Unutma: Sağlam bir mimari, gevşek bağlı sınıflarla başlar! 💡


;