Dependency Injection SOLİD in D si Dependecy Inversion.
Dependency = Bağımlılık , Dependecy Injection = Bağımlılık Enjeksiyonu.
Dependency Inversion = Bağımlılığın ters çevrilmesi
Dependency Inversion prensiptir. Bu prensibi somut olarak pratikte uygulamanın kendisi Dependency Injection Design Pattern ınıdır.
Dependency Injection bağımlılıkların tersine dönüşebilmesi için yapılması gerekn bir design patterndır.
A sınıfında B sınıfının nesnesine ihtiyacımız var. Normalde A içerisinde new B(); dememiz gerekiyor. Bu operasyonu yaptığımızda B sınıfından nesne oluşturmuş oluyoruz ve ihtiyacımızı gidermiş oluyoruz. Dependency Injection der ki herhangi bir sınıfta herhangi bir noktasında başka bir sınıfın nesnesine ihtiyacın varsa o sınıfın nesnesini New operatörü ile oluşturmamaya dikkat et Eğer bunu yaparsan bağımlılık oluşur. A B ye artık bağımlıdır. Bundan sonra B nin üzerinde yapılan tüm değişiklikler A yı etkileyecektir. B nin constructor ında herhangi bir şeyi değiştirdik, A patladı, A ya gelip burdaki constructor a ilgili değişikliği uygulamamız gerekir. B nin üzerinde yapılan herhangi bir çalışma her daim A ya yansayacaktır. B deki bağımlılığı mümkün mertebe A dan soyutlamalıyız. New operatörü ile kurduğumuz bağımlılık neticesinde A yı her türlü B nin etkisi altında bırakmış oluyoruz.
Bir sınıfın başka bir sınıfa olan bağımlılığını ortadan kaldırabilmek için yapmamız gereken bir kaç operasyondan biri enjekte etmektir.
A sınıfı B sınıfına bağımlı olsun ancak A sınıfının ihtiyacı bir gün değişti ve A sınıfı C sınıfına gidebilir. D ve E sınıfına gidebilir. Farklı sınıflara ihtiyacımız olabilir. İhtiyaç farklılığına göre B deki somut bağımlılığı ortadan kaldırabilmeli ve hızlı bir şekilde diğer bağımlılıkları devreye sokabilmeliyiz. A B ye bağlı C sınıfına ihtiyaç duyduğunda B nin kodlarını silip C yi eklemek, D ye ihtiyaç duyduğunda C nin kodlarını silip D yi eklemek… Her çalışma yapacağımız sınıfla ilgili operasyonlarda bir öncekini silip yenisini eklemek… Bağımlılık durumlarında ihtiyaçlar değiştikçe kaynak kod değişir.
B : IClass
C: IClass
D: IClass
A sınıfıda IClass obj; IClass türünden obj parametresi alsın bu şekilde yeri geldiğinde B yi yeri geldiğind C,D ‘yi karşılayacak şekilde bir yapı oluştururuz.
İhtiyacımız doğrultusunda yapılması gereken operasyon her neyse davranış değişiyorsa burdaki davranışa göre kodu değiştirmek zorunda değiliz. İlgili nesneyi operasyona dışarıdan enjekte edebiliriz. IClass arayüzü sayesinde elimizdeki operasyonel sınıfları sisteme, algoritmaya, çalışmaya dahil edebiliyoruz. Dahil etme esnasında ekstradan kodu değiştirmemize gerek yoktur. Bu kalıtımsal stratejiyi uygulamak dependect injection dır.
Sınıfın içerisinde başka bir sınıfa ihtiyacımız varsa bunu new leyerek oluşturma bunu parametreden al.
Bir sınıf başka bir sınıfı kendi içerisinde new operatörü ile instance ını oluşturuyorsa o sınıf ilgili sınıfa bağımlı oluyor. Oluşturulan sınıfa oluşturan sınıf bağımlı oluyor. Bağımlılığı ortadan kaldırabilmek için bu sınıfı biz parametreden almayı tercih ediyoruz. Çünkü gün gelir davranış değişir başka muadil sınıfları devreye sokmamız gerekir, ortak bir base oluşturuyoruz bu base üzerinden bütün operasyona ilgili sınıfları dahil ediyoruz.
Bu yapıya Inversion of Control denmektedir.
A B ye ihtiyaç duyuyordu ancak A; B,C,D,E ye ihtiyaç duyabilir. Böyle bir durumda hepsini referans vererek yazdığımız koddaki maliyeti arttırmaktansa, kod karmaşasına neden olmaktansa bunun için bu işlemi otomatik olarak yapacak container lara bu sınıfların nesnelerini veririz ve ihtiyaç doğrultusunda bu container üzerinden bu nesneleri elde ederiz. Buna IoC (Inversion of Control) denir. Control ün ters çevrilmesidir.
Kontrol tersine döndü, ITasit türünden bir parametre alıyorsam buraya taksi de gelebilir otobüs de gelebilir. Artık taksinin gelip gelmeyeceğini otobüsün kullanılıp kullanılmayacağının kararını develepor vermeye başladı. Bu sınıfı kullanırken ister otobüs nesnesi veririm ister taksi nesnesi veririm ona göre çalışırsın.
Yukarıda belirtilen services.Add(new ServiceDescriptor(typeof(ConsoleLog), new ConsoleLog())); default olarak Singleton dur. Scoped ya da Transient olarak davranış sergilemesini istiyorsak onu belirtiyoruz.
services.AddSingleton<ConsoleLog>(); services.AddScoped<ConsoleLog>(); services.AddTransient<ConsoleLog>();
Constructor da parametre alan ve almayan hali yukarıda örneklendirilmiştir.
IoC yapılanmasını kullanırken aynı işi yapan servisleri ortak bir türün altında toplarız. Örneğin otobüs ve taksi yi ITasit interface inin altında topluyoruz. Çünkü istediğim zaman istediğimi çağırabileyim, dahil edebileyim, dışarıdan enjekte edebileyim. Container a vereceğimiz nesneleri bir ortak interface le abstraction a tabi tutarız.
Gün geldi ihtiyacımız değişti tek yapmamız gereken, ConsoleLog yerine TextLog yazmamızdır.
services.AddScoped<ILog>(p => new TextLog());
services.AddScoped<ILog, TextLog>(); //Bir tane ILog türünde container dan nesne koy, TextLog nesnesi koy. TextLog un ILog dan türemiş olması gerekiyor. TextLog dan nesne üretilebilir constructor ı default olan, boş olan, parametresi olan bir nesne olması gerekiyor.
Controller Constructor’ından Nesne Talebinde Nasıl Bulunulur?
Controller ların constructorları üzerinden IoC container ının içindeki nesneleri talep edebilmekteyiz.
Farklı türlerde servisleri davranışsal olarak operasyona dahil etmek istediğimizde bu şekilde IoC yapılanmasıyla efektif çözüm getirebilmekteyiz. Bu şekilde çalışmasaydık ilgili controller içerisinde ihtiyaç değiştikçe kodu değiştirmemiz gerekecekti bu da bize ekstradan külfet demekti. Bu tasarım sayesinde lüzumsuz kodları yazmaktan kodumu arındırmış oluyoruz.
Action Bazında Nesne Talebinde Nasıl Bulunulur? FromServices Attribute’u
Hangi nesneyi bekliyorsak o nesneye dair parametrede, FromServices ile işaretlenmiş bir parametre koymamız gerekiyor.
ILog log => burdaki değeri Services dan yani containerdan getir burdaki parametreye bağla demiş oluyoruz.
View’de Nesne Talebinde Nasıl Bulunulur? @inject
istediğimiz yerde log property sini kullanıp gerekli operasyonları sağlayabiliriz. View lerdende bu şekilde ilgili containerdan nesneleri talep edebiliyoruz.