.NET Core Dependency Injection Rehberi
Yazılım projeleri büyüdükçe sınıflar arasındaki bağımlılıklar da artmaya başlar. Başlangıçta küçük ve yönetilebilir görünen yapılar, zamanla birbirine sıkı bağlı hale gelir ve bu durum kodun sürdürülebilirliğini zorlaştırır.
Bir sınıfın ihtiyaç duyduğu nesneleri kendi içinde üretmesi ilk bakışta pratik görünebilir. Ancak bu yaklaşım:
- Test yazmayı zorlaştırır
- Kod tekrarını artırır
- Esnekliği azaltır
- Bakım maliyetini yükseltir
İşte tam bu noktada Dependency Injection (DI) devreye girer.
Dependency Injection, modern .NET uygulamalarında bağımlılık yönetimini kolaylaştıran ve kodun daha modüler hale gelmesini sağlayan temel mimari yaklaşımlardan biridir.
Dependency Injection Nedir?
Dependency Injection, bir sınıfın ihtiyaç duyduğu bağımlılıkların sınıf içinde oluşturulması yerine dışarıdan verilmesi prensibine dayanır.
Yani bir sınıf:
- Nesne üretmekle uğraşmaz
- Sadece ihtiyacı olan arayüzlere bağımlı olur
- Gerçek implementasyonları DI container yönetir
Bu yaklaşım sayesinde kod daha esnek, daha test edilebilir ve daha sürdürülebilir hale gelir.
Dependency Injection Neden Önemlidir?
DI’nin temel amacı sınıfları birbirine sıkı bağlı olmaktan kurtarmaktır.
Örneğin bir ödeme sistemi düşünelim.
Eğer ödeme servisi doğrudan belirli bir kredi kartı sağlayıcısına bağlıysa, ileride farklı bir ödeme sistemine geçmek oldukça zor hale gelir.
Ancak Dependency Injection yaklaşımında:
- Ödeme servisi yalnızca bir interface’e bağımlı olur
- Gerçek implementasyon dışarıdan verilir
- Sistem kolayca genişletilebilir hale gelir
Bu yapı sayesinde:
- PayPal
- Stripe
- iyzico
- Shopier
gibi farklı sağlayıcılar kolayca sisteme entegre edilebilir.
.NET Core’da Yerleşik Dependency Injection Yapısı
Eskiden .NET projelerinde Autofac, Ninject veya Castle Windsor gibi üçüncü parti DI kütüphaneleri yoğun şekilde kullanılıyordu.
Ancak ASP.NET Core ile birlikte Microsoft artık yerleşik bir Dependency Injection container sunuyor.
Bu sayede ek bir kütüphane kullanmadan servis kayıtları yapılabiliyor.
Service Lifetime Türleri
.NET Core DI container içinde servislerin yaşam süreleri belirlenebilir.
1. Transient
Her kullanımda yeni bir nesne oluşturulur.
- Hafif servislerde tercih edilir
- Stateless yapılarda uygundur
- Fazla kullanılırsa performansı etkileyebilir
2. Scoped
Web uygulamalarında her HTTP request için tek bir nesne oluşturulur.
- DbContext gibi yapılarda yaygın kullanılır
- Request bazlı veri yönetimi sağlar
- ASP.NET Core projelerinde en sık kullanılan lifetime’dır
3. Singleton
Uygulama boyunca tek bir nesne paylaşılır.
- Cache servisleri
- Configuration servisleri
- Statik veri yöneten yapılar
için kullanılabilir.
Ancak yanlış Singleton kullanımı bellek problemlerine neden olabilir.
Constructor Injection Neden Tercih Edilir?
Dependency Injection kullanımında en yaygın yaklaşım constructor injection yöntemidir.
Bu yaklaşım sayesinde bağımlılıklar sınıf oluşturulurken verilir.
Constructor injection:
- Daha okunabilir kod sağlar
- Zorunlu bağımlılıkları net gösterir
- Test süreçlerini kolaylaştırır
- Service locator anti-pattern problemini önler
Modern .NET projelerinde en sağlıklı yaklaşım constructor injection kullanmaktır.
Factory Pattern ile Dependency Injection
Bazı servislerin oluşturulması standart dependency injection yaklaşımından daha karmaşık olabilir.
Örneğin:
- Ortam bazlı servis üretimi
- Runtime configuration yönetimi
- Dinamik provider seçimi
gibi durumlarda factory pattern kullanımı oldukça faydalıdır.
Factory yaklaşımı sayesinde servislerin nasıl oluşturulacağı merkezi şekilde yönetilebilir.
Generic Servis ve Repository Yapıları
Birçok projede tekrar eden repository veya servis yapıları bulunur.
Dependency Injection sayesinde generic servis kayıtları yapılabilir.
Bu yaklaşım:
- Kod tekrarını azaltır
- Bakımı kolaylaştırır
- Daha modüler yapı sağlar
Özellikle generic repository yapılarında DI büyük kolaylık sağlar.
Birden Fazla Implementasyon Kullanımı
Bazı durumlarda aynı interface’in birden fazla implementasyonu olabilir.
Örneğin:
- Farklı SMS servisleri
- Çeşitli ödeme sağlayıcıları
- Alternatif log sistemleri
Dependency Injection sayesinde bu implementasyonlar kolayca yönetilebilir.
Hangi implementasyonun kullanılacağı:
- Strategy Pattern
- Factory yaklaşımı
- Configuration yönetimi
ile belirlenebilir.
Ortam Bazlı Dependency Injection
ASP.NET Core uygulamalarında development, staging ve production ortamlarında farklı servisler kullanılabilir.
Örneğin:
- Development ortamında fake payment service
- Production ortamında gerçek ödeme sağlayıcısı
tercih edilebilir.
Dependency Injection container bu geçişleri oldukça kolay hale getirir.
Middleware ve Dependency Injection İlişkisi
ASP.NET Core middleware yapısı tamamen Dependency Injection ile uyumlu çalışır.
Middleware bileşenleri:
- Logger servisleri
- Cache servisleri
- Authentication servisleri
- Monitoring araçları
gibi bağımlılıkları doğrudan kullanabilir.
Bu yapı merkezi request yönetimi açısından büyük avantaj sağlar.
Dependency Injection ve Test Edilebilirlik
DI’nin en büyük avantajlarından biri test süreçlerini kolaylaştırmasıdır.
Çünkü gerçek bağımlılıklar yerine:
- Mock nesneler
- Fake servisler
- Stub yapılar
kullanılarak test yazılabilir.
Bu yaklaşım sayesinde:
- Veritabanına bağlanmadan test yapılabilir
- Harici API bağımlılıkları kaldırılabilir
- Sadece business logic test edilebilir
Modern test mimarilerinde Dependency Injection kritik rol oynar.
Clean Architecture ve Dependency Injection
Dependency Injection modern yazılım mimarilerinin temel taşlarından biridir.
Özellikle:
- Clean Architecture
- Onion Architecture
- Domain Driven Design
gibi yapılarda yoğun şekilde kullanılır.
Bu mimarilerde:
- Business katmanı yalnızca abstraction’a bağımlıdır
- Gerçek implementasyon infrastructure katmanında bulunur
- DI container bağımlılıkları runtime’da eşler
Bu yaklaşım uygulamanın daha modüler ve değişime açık olmasını sağlar.
Dependency Injection Kullanırken Dikkat Edilmesi Gerekenler
- Gereksiz Singleton kullanımından kaçınılmalıdır
- Ağır servisleri sürekli Transient yapmak performansı düşürebilir
- Constructor injection tercih edilmelidir
- Circular dependency problemlerine dikkat edilmelidir
- Service locator yaklaşımından uzak durulmalıdır
Yanlış yapılandırılmış bir DI sistemi zamanla performans ve bakım problemlerine neden olabilir.
Sonuç
Dependency Injection, modern .NET projelerinin vazgeçilmez mimari parçalarından biridir.
Esneklik, test edilebilirlik ve sürdürülebilirlik açısından büyük avantaj sağlar.
Özellikle:
- ASP.NET Core projelerinde
- Microservice mimarilerinde
- Kurumsal backend sistemlerinde
- Clean Architecture yapılarında
Dependency Injection kullanımı artık standart hale gelmiştir.
Doğru kullanıldığında DI yalnızca bağımlılık yönetimi sağlamaz; aynı zamanda projenin uzun vadede daha temiz, daha ölçeklenebilir ve daha yönetilebilir olmasına katkı sağlar.
Modern yazılım geliştirme süreçlerinde Dependency Injection yalnızca bir teknik değil, sürdürülebilir mimari kurmanın temel yaklaşımlarından biridir.