Dependency Injection — IoC Yapılanması

Burak Can Duran
5 min readApr 10, 2024

--

Yazılım geliştirme sürecinde, sınıflar arasındaki bağımlılıkların yönetimi ve kontrolü büyük önem taşır. Bağımlılıkların etkili bir şekilde yönetilmesi, kodun esnekliğini, bakımını ve yeniden kullanılabilirliğini artırabilir. Bu noktada, Dependency Injection (Bağımlılık Enjeksiyonu) ve Inversion of Control (IoC) gibi kavramlar ön plana çıkar.

Dependency Injection Tasarım Deseni
Dependency Injection Tasarım Deseni

Dependency Injection Nedir ?

Dependency Injection, yazılım geliştirme sürecinde sıkça kullanılan bir desen ve tekniğidir. Temel olarak, bir sınıfın bağımlılıklarını dışarıdan alarak, sınıflar arasındaki sıkı bağımlılıkları azaltır. Örneğin, bir sınıfın başka bir sınıfın nesnesine ihtiyacı olduğunda, bu nesneyi new() operatörü ile oluşturmak yerine, dışarıdan enjekte etmek mümkündür. Bu, sınıflar arasındaki bağımlılıkları azaltır ve kodun daha esnek hale gelmesini sağlar.

A sınıfı içerisinde B sınıfının nesnesini new anahtar kelimesi ile oluşturuyorum. Bu durumda, B sınıfındaki herhangi bir değişim A sınıfını etkileyecektir. new ile nesne oluşturulması durumu zaten bağımlılığı getirdiğinden, A sınıfı B sınıfına bağımlıdır. Bu yüzden mümkün olduğunca B sınıfını A sınıfından soyutlamalıyız. Bu soyutlama olayı Dependency Injection olmaktadır. Sınıfımız içerisinde bir başka sınıfa ihtiyacımız varsa bu sınıfı new() ile oluşturmamalıyız, o sınıfı parametreden almalıyız. Yani gerekli olan nesne ya constructordan ya da setter metodu ile parametre olarak ilgili sınıfa alınması gerekir. Bu şekilde iki sınıfta birbirinden izole edilmiş olur.

Örneğin; Dependency Injection ve IoC Kullanımı ile Taşıt Hareketlerini Yönetme

public interface ITasit
{
void HareketEt();
}
//ITasit arayüzü, taşıt nesnelerinin ortak davranışlarını tanımlar.
public class Otobus : ITasit
{
public void HareketEt()
{
Console.WriteLine("Otobüs hareket ediyor.");
}
}
/*ITasit arayüzünü uygular.
HareketEt() metodu, otobüsün hareket etme işlemini gerçekleştirir.
Bu durumda, sadece bir konsol çıktısı verir. */
public class Taksi : ITasit
{
public void HareketEt()
{
Console.WriteLine("Taksi hareket ediyor.");
}
}
/*Taksi Sınıfı:
ITasit arayüzünü uygular.
HareketEt() metodu, taksinin hareket etme işlemini gerçekleştirir.
Bu durumda, sadece bir konsol çıktısı verir.*/
public class Uygulama
{
private readonly ITasit _tasit;

public Uygulama(ITasit tasit)
{
_tasit = tasit;
}

public void TasitlaHareketEt()
{
_tasit.HareketEt();
}
}
/* ITasit arayüzünü kullanarak constructor enjeksiyonu yapar.
TasitlaHareketEt() metodu, enjekte edilen taşıt nesnesinin
HareketEt() metodunu çağırır.*/

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITasit, Otobus>(); // ITasit arayüzü için Otobus sınıfının kullanımı
//.AddSingleton<ITasit, Taksi>(); // Taksi sınıfını kullanmak için bu satırı yorum satırından çıkarın
}
/*ConfigureServices metodu, servislerin eklenmesi için kullanılır.
Burada ITasit arayüzü için Otobus sınıfının kullanımı yapılmıştır.
Opsiyonel olarak, Taksi sınıfının kullanımı için yorum satırından çıkarılabilir.*/
 public class TasitController : ControllerBase
{
private readonly Uygulama _uygulama;

public TasitController(Uygulama uygulama)
{
_uygulama = uygulama;
}

[HttpGet]
public IActionResult HareketEt()
{
_uygulama.TasitlaHareketEt();
return Ok("Taşıt hareket etti.");
}
}
/*ControllerBase sınıfından türetilmiş bir controller sınıfıdır.
HareketEt() adında bir GET endpoint'i bulunur.
Constructor enjeksiyonu kullanarak Uygulama sınıfını alır.
HareketEt() metodu, Uygulama sınıfının TasitlaHareketEt()
metodunu çağırır ve ardından bir mesaj döndürür.*/

Bu örnek, Dependency Injection ve Inversion of Control (IoC) prensiplerini kullanarak taşıt nesnelerinin hareketlerini yönetmeyi gösterir. Bu sayede, sınıflar arasındaki bağımlılıklar azaltılır ve kodun daha esnek ve bakımı daha kolay hale getirilir.

IoC nedir ?

IoC ise, Dependency Injection’ın bir uygulamasıdır. IoC prensibi, bir bileşenin kontrolünün dış bir kaynaktan sağlanmasıdır. Dependency Injection, bu prensibi uygulamanın bir yoludur çünkü sınıflar arasındaki kontrolü dışarıdan sağlar. Yani, bir sınıfın başka bir sınıfa olan bağımlılığını azaltmak için IoC prensibini kullanarak Dependency Injection desenini uygulayabiliriz.

Bir sınıf çok sayıda arayüze yani bir başka sınıfın nesnesine, bir başka operasyona ihtiyaç duyabilir. A sınıfı hem B sınıfına, hem C sınıfına, hem D sınıfına aynı anda ihtiyaç duyabilir. Böyle bir durumda hepsine aynı anda referans verip yazdığımız koddaki maliyeti arttırıp, aynı zamanda kod karmaşasına sebep olmaktansa, bu işlemi otomatik olarak yapacak bir yapı
kurmamız gerekiyor. Bunun için de yukardaki resimde gösterildiği gibi containerlara bu sınıfların nesnelerini veririz ve ihtiyaç doğrultusunda bu container üzerinden ilgili nesneleri elde edebiliriz. Bu yapıya IoC (Inversion Of Control) denir yani kontrolün tersine çevrilmesi.

Asp.NET Core’ da IoC Yapılanması

ASP.NET Core, “Inversion of Control” (IoC) prensibine dayalı olarak çalışır. Bu, bir bileşenin kendi bağımlılıklarını kontrol etmek yerine dışarıdan alması ve bu bağımlılıkları bir bağımlılık enjeksiyonu (dependency injection) konteyneri aracılığıyla alması anlamına gelir. ASP.NET Core’un IoC’si, hizmetlerin kaydedilmesi, yönetilmesi ve çözülmesi için bir altyapı sağlar.

ASP.NET Core’da IoC, IServiceCollection arayüzü ve ConfigureServices yöntemi ile yapılandırılır. ConfigureServices yöntemi, uygulamanın başlatılması sırasında çağrılır ve hizmetlerin kaydedilmesi için kullanılır. IServiceCollection, hizmetlerin kaydedilmesini, bağımlılıkların çözülmesini ve farklı yaşam döngülerinin belirlenmesini sağlar.

ASP.NET Core’un IoC konteyneri, üç farklı davranış alabilir:

  1. Singleton: Singleton servisler, uygulama boyunca yalnızca bir örneği korur ve her istekte aynı örneği döndürür. Bu, bir uygulama boyunca paylaşılan durumların saklanması veya pahalı nesnelerin yeniden oluşturulmasının önlenmesi için kullanılır.
Singleton

2.Scoped: Her request başına bir nesne üretir ve o request pipeline’nında olan tüm isteklere o nesneyi gönderirir. Scoped’ da her request için oluşturulan nesne iş bittikten sonra imha/dispose edilir.

Scoped

3.Transient: Her request’in her talebine karşılık bir nesne üretir ve gönderir.

Transient

Dependency Inversion ilkesi nedir, dependency injection ile ilişkisi nedir ?

Dependency Inversion ilkesi ise, sınıflar arasındaki bağımlılıkların yönetimini belirler. Bu ilkeye göre, yüksek seviyeli bileşenler düşük seviyeli bileşenlere doğrudan bağımlı olmamalıdır. Bunun yerine, her ikisi de soyut arayüzler üzerinden bağımlı olmalıdır. Dependency Injection, bu ilkeyi uygulamanın bir yolu olarak kabul edilir çünkü sınıflar arasındaki bağımlılıkları soyut arayüzler üzerinden yönetmek için kullanılır.

SOLID

Sonuç Olarak:

Dependency Injection ve IoC, yazılım geliştirme sürecinde kodun daha esnek, bakımı daha kolay ve yeniden kullanılabilir olmasını sağlayan önemli kavramlardır. Dependency Injection, sınıflar arasındaki bağımlılıkları azaltmanın etkili bir yoludur ve IoC prensibini uygulamanın bir yoludur. Dependency Inversion ilkesi ise, sınıflar arasındaki bağımlılıkların yönetimini belirler ve bu ilkeyi uygulamak için Dependency Injection ve IoC gibi teknikler kullanılabilir. Bu nedenle, bu kavramları anlamak ve etkili bir şekilde uygulamak, yazılım geliştirme sürecinde önemlidir.

--

--