.NET Core’da Dependency Injection(DI)
Dependency injection (bağımlılık enjeksiyonu), SOLID prensiplerinin sonuncusu olan “Dependency Inversion” prensibini uygulayan bir design pattern’dir. Bu pattern, bir bileşenin diğer bileşenlere olan bağımlılıklarını doğrudan tanımlamak yerine, dışarıdan gelen bir arayüzle bu bağımlılıkları enjekte etmek yoluyla sağlar.
Bu pattern, bir uygulamanın kodunun daha esnek, bakımı daha kolay ve test edilebilir olmasını sağlar. Bağımlılık enjeksiyonu sayesinde, bir bileşenin içinde kullanılan diğer bileşenlerin kodu değiştirilmeden, bileşenin davranışı ve işlevselliği değiştirilebilir veya farklı bir bileşenle değiştirilebilir.
Bağımlılık enjeksiyonu, birçok programlama dilinde ve framework’te kullanılabilir ve özellikle büyük ve karmaşık uygulamalar için önemlidir. Bu teknik, yazılımın kalitesini artırırken, uygulamanın tasarımını daha sade ve anlaşılır hale getirir.
ASP.NET Core’da “Dependency Injection” built-in olarak gelmektedir. Interface veya Abstract bir sınıf ile soyutlanmış sınıflarımızı 3 farklı şekilde inject ederek kullanabiliriz. Bunlar;
- Constructor Injection: En çok kullanılan yaklaşımdır. Soyut sınıfın nesnesini bağımlı olan sınıfın constructor metoduna geçirerek nesne elde edilir.
public class CustomerGlobalSearchService
{
protected readonly ISettingService _settingService;
public CustomerGlobalSearchService(ISettingService settingService)
{
_settingService = settingService;
}
}
- Method Injection: Bazen sadece bir metodta işlem yaparken bağımlılık kullanmaya ihtiyaç duyabiliriz. Bu durumda soyut nesneyi bütün sınıfa inject etmektense sadece methoda parametre olarak geçebiliriz. Aşağıdaki örnekte ILog tipindeki nesne sadece Index metodunda inject edilmiştir.
public IActionResult Index([FromServices] ILog log)
{
log.info("Index method executing");
return View();
}
- Property Injection: Property injection aynı zamanda setter injection’da denir. İhtiyaca göre bir objenin property’e set edilmesi. Aşağıdaki örnekte “employeeBL.EmployeeDataObject = new EmployeeDAL();” satırında görülebilir.
class Program
{
static void Main(string[] args)
{
//Create an Instance of Client Class i.e. EmployeeBL
EmployeeBL employeeBL = new EmployeeBL();
//Inject the Dependency Object using the Public Property of the Client Class
employeeBL.EmployeeDataObject = new EmployeeDAL();
List<Employee> ListEmployee = employeeBL.GetAllEmployees();
foreach (Employee emp in ListEmployee)
{
Console.WriteLine($"ID = {emp.ID}, Name = {emp.Name}, Department = {emp.Department}");
}
Console.ReadKey();
}
}
Örnek Proje
Basit bir örnek ile Dependency Injection’un nasıl nasıl kullanıldığını göstermek istiyorum. Aşağıdaki gibi ASP.NET Core’da Web Api olarak yazılmış bir projemiz olsun. Projemiz bize Student nesnesi ile işlemler yapıp sonuç döndürsün. Proje içerisinde Repository ve Service katmanları için kullandığımız Interface’leri Container’a register edelim ve kullanalım. İlk olarak domain objemizi aşağıdaki gibi yaratalım.
Sonrasında yukarıda oluşturduğumuz Student için IStudentRepository interface ve StudyRepository Class’ını oluşturalım.
Yukarıda oluşturduğumuz IStudentRepository.cs interface’i aşağıda tanımlayacağımız StudentService.cs sınıfına constructor-injected parameter olarak vereceğiz.
Yukarıda kullandığımız StudentRepository ve StudentService nesnelerini Container’a implementasyonlarını belirterek register etmemiz gerekiyor. Bunun için Startup.cs’de proje ilk run edildiğinde ilgili kullanılan bağımlılıkları register edeceğiz. Startup.cs de bulunan ConfigureServices adlı metot register işlemlerini yapmak için default gelen bir metottur. Aşağıdaki gibi tanımlamalarımızı yapiyoruz.
Container Register
ASP.NET Core’da default gelen DI Container’a, sınıf ve servisleri default gelen 3 farklı extension metod ile yapabiliriz.
Bunlar;
- AddScoped()
- AddTransient()
- AddSingleton()
AddScoped() metodu ile register edilen nesneler her request scop’unda sadece bir instance oluşturulur.
AddTransient() metodu ile register edilen nesneler her çağrıldığında yeni bir instance oluşturulur.
AddSingleton() metodu ile register edilen nesneler uygulama başlarken sadece bir tane instance oluşur.
Yukarıda görüldüğü üzere IStudentRepository ve IStudentService arayüzlerinin implementasyonlarını belirterek AddScoped() metodunu kullanarak register ettik. Buradaki AddScoped() metodu bize gelen her bir istek için oluşturulacak nesneden sadece bir tane instance oluşturulacağının garantisini veriyor.
Controller Tarafında Kullanma
Aşağıdaki gibi StudentController içerisinde Container’da register edilen instance’ları kullanarak geriye StudentList geri dönderiyoruz.
ASP.NET Core için Dependency Injection kullanım örneği bu kadardır. Burada Constructor-Injected olarak gerekli nesneleri üretmiş olduk. Yukarıdaki end-point’e istek atarak geriye “Student-1” ve “Student-2” öğrencilerinin bulunduğu diziyi dönüyor.
[
{
"id": "8bf4a343-347c-4557-aa70-52691629f1a7",
"name": "Student-1"
},
{
"id": "e760844b-53a2-44c5-87a9-14dcbb59d0a4",
"name": "Student-2"
}
]
Umarım faydalı olmuştur.