Bu yazımda sizlere Inversion of Control ve Dependency Injection konularından bahsedeceğim. Inversion of Control aslında alışıla gelmiş kodlama tarzımızı biraz değiştiriyor. Nesnelerin birbirine sıkı sıkıya bağlı (Tightly Coupled) olmasını azaltılıyor. Soyut (Abstract) bir yapı kuruyor.
Örneklerle ne demek istediğimi daha iyi anlayacaksınız. Bu iki konuyu öğrenmek için Loglama işlemi yapan bir exe'miz olduğunu düşünelim. Bazen veri tabanına (DB) loglama bazen de dosyaya loglama ihiyacımız olduğunu düşünelim. Loglama için aşağıdaki gibi bir yapı oluşturup console application' ı yazalım.
Okurken ne dinlemeli ?
Bir console application oluşturup aşağıdaki gibi bir isimlendirme ve yapı kuralım:
IOC olmadan düz mantıkla Log yapısı kuralım:
public class NonIOCLogging
{
private NonIOCDBLogging _logging;
public NonIOCLogging()
{
_logging = new NonIOCDBLogging();
}
public void Log()
{
_logging.Log();
}
}
public class NonIOCDBLogging
{
public void Log()
{
Console.WriteLine("Logging to DB.");
}
}
Görüldüğü gibi NonIOCLogging sınıfında NonIOCDBLogging sınıfını çağırarak logging nesnesi instance' ı oluşturuyoruz. Kilit nokta burası. Şimdi Program.cs' de NonIOCLogging sınıfını kullanalım.
class Program
{
static void Main(string[] args)
{
//non -ioc
NonIOCLogging logmanager = new NonIOCLogging();
logmanager.Log();
...
Buraya kadar her şey güzel ihtiyacımıza yönelik bir kod yazmış olduk fakat projemiz büyüdü istekler arttı ve müşterimiz artık FileLog olmasını istedi. İşte o zaman new NonIOCDBLogging(); yazan her yeri FileLogging adında yeni bir class oluşturup instance alınan yerleri replace mi etmek gerekli ? Kaç kere , nerelerde bu instance'ler var ? NonIOCLogging nesnesini NonIOCDBLogging nesnesine sıkı sıkıya bağlılıktan kurtarıp daha generic , soyut ve nesnelerin birbirine gevşek bağlı (Loosely Coupled) olduğu bir şeyler yapmalıyız. İstediğimize kolayca tek bir yerden DBLogging ya da FileLogging arasında değişim yapabilmeliyiz. Küçük projelerde belki mantıklı olmasa da kurumsal ve büyük projelerde bu yaklaşım bize yarar sağlayacaktır.
Şimdi IOC (Inversion of Control) mantığı ile kodumuzu yenileyelim ve IOC yaklaşımını yapmak için gerekli olan DI (Dependency Injection) implementasyonunu ve çeşitlerini öğrenelim. Sizler için IOC mantığında kodladığım kısımları IOCLogging adında bir klasörde topladım. IOC ve DI 'nın temeli olan Interface 'imizi oluşturarak işe başlayalım.
public interface ILogging
{
void Log();
}
Logging sınıfımızı oluşturalım ve bu Interface vasıtası ile Constructor Injection oluşturalım. DI çeşitlerine yazının devamında bahsedeceğim.
public class Logging
{
private ILogging _logging;
public Logging(ILogging ie)
{
_logging = ie;
}
public void Log()
{
this._logging.Log();
}
}
Gelelim istediğimiz türden Log sınıflarını oluşturmaya DBLog ve FileLog:
public class DBLogging:ILogging
{
public void Log()
{
Console.WriteLine("Logging to DB.");
}
}
public class FileLogging :ILogging
{
public void Log()
{
Console.WriteLine("Logging to file.");
}
}
Görüldüğü gibi iki sınıfımız da ILogging interface 'nı miras almaktadır. Kolay bir implentasyon ile Program.cs 'de kullanalım.
Logging logmanager_ioc = new Logging(new DBLogging());
logmanager_ioc.Log();
Logging logmanager_ioc1 = new Logging(new FileLogging());
logmanager_ioc1.Log();
Program.cs 'de başka sınıflarda kod değişikliği yapmadan constructor yardımı ile istediğimiz Log yapısını kurmuş olduk.
Yukarıdaki örneğimiz constructor türünden bir DI idi .Dependency Injection başka çeşitlerde de vardır.
Property ile Dependency Injection :
public class LoggingDIviaProperty
{
private ILogging _logging;
public ILogging MyEvent
{
set
{
_logging = value;
}
}
public void Log()
{
this._logging.Log();
}
}
Program.cs
LoggingDIviaProperty
logmanager_ioc2 = new
LoggingDIviaProperty();
logmanager_ioc2.MyEvent = new DBLogging();
logmanager_ioc2.Log();
Metod ile Dependency Injection :
public class LoggingDIviaMethod
{
private ILogging _logging;
public void
GetEvent(ILogging myevent)
{
this._logging = myevent;
}
public void Log()
{
this._logging.Log();
}
}
Program.cs 'de :
LoggingDIviaMethod logmanager_ioc3
= new LoggingDIviaMethod();
logmanager_ioc3.GetEvent(new DBLogging());
logmanager_ioc3.Log();
Service Locator ile Dependency Injection:
Son olarak Service Locator ile Dependency Injection yapacağız bu yapı aslında manuel olarak IOC Container tanımlamak gibidir. IOC container mantığıdır.
public class LoggingDIviaServiceLocator
{
private ILogging _logging = null;
EventLocator el = new EventLocator();
public LoggingDIviaServiceLocator(int index)
{
this._logging = el.LocateEvent(index);
}
public void Log()
{
this._logging.Log();
}
class EventLocator
{
public ILogging LocateEvent(int index)
{
if (index == 1)
return new DBLogging();
else if (index == 2)
return new FileLogging();
else
return null;
}
}
}
Program.cs 'de :
LoggingDIviaServiceLocator
logmanager_ioc4 = new
LoggingDIviaServiceLocator(1);
logmanager_ioc4.Log();
Console uygulamamızı çalıştırdığımızda index'i 1 verdiğimiz için DBLogging 'in çalıştığını göreceğiz.
Projenin tam haline buradan ulaşabilirsiniz. Umarım faydalı olmuştur.
Sağlıkla kalın,
Huzurla kalın.
Kaynak:
https://www.c-sharpcorner.com/UploadFile/cda5ba/dependency-injection-di-and-inversion-of-control-ioc/
Hiç yorum yok:
Yorum Gönder