Asp.net MVC mimarisini benim için değerli kılan özelliklerinden başında genişletilmeye uygun olarak tasarlanmış olması gelmektedir.
Bu yazımızda Asp.Net MVC yaşam alanına giren bir isteği(request) ilk karşılayan Controller mekanizmasının özelleştirilmesi üzerinde duracağız. MVC mimarisinde Controller tipleri belli kurallar dahilinde tanımlanmıştır. Bu kuralların dışına çıkmak istediğimizde kendi isteğimize göre özel kurallar oluşturarak sisteme dahil etmemiz gerekmektedir. Default olarak tanımlanmış Controller kurallarından biri de Controller sınıflarının kurucu metodları (constructor) parametresiz olmasıdır.
Bu yazımızda parametresiz constructor metodunu ihlal ettiğimizde karşılaşacağımız sorunlar ve çözümleri üzerinde duracağız.
Parametresiz constructor kuralını ihlal ettiğimizde hemen bir hata ile karşılaşırız. Burada yapmak istediğimiz IoC (Inversion of Control) mantığında Controller sınıfına dışarıdan bir nesne(securityService) enjekte etmektir. Bu işlem için piyasadaki Ioc kütüphanelerini kullanabiliriz. Piyasada şu anda kullanılan kütüphaneler widsor, structuremap, ninject,… şeklinde sıralanabilir. Şu anda konumuz olmasa da IoC kütüphanelerinin yaptığı işten hemen kısaca bahsedelim. IoC kütüphaneleri interface gibi soyut tiplere karşılık olarak belirlediğimiz somut sınıflara ait nesneleri ihtiyaç duyduğumuzda oluşturarak bize sunarlar. Bu sayede “new” anahtar sözcüğü ile Controller içinde nesne oluşturarak somut tiplere bağımlı kalmamış oluruz.
Bu kısa notun ardından kendi tasarladığımız ControllerFactory sınıfımızı oluşturmaya başlayalım.
public class IocControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType) { return (IController)ObjectFactory.GetInstance(controllerType); } }
DefaultControllerFactory sınıfının GetControllerInstance metodunu ezerek Controller nesnesi oluşturma işlemini StructureMap IoC container kütüphanesine yükledik. StructureMap kütüphanesi, önceden tanımladığımız interface ve sınıf eşleştirmesini yaparak constructor parametresi olarak kullanılan interface tipine karşılık bir somut nesne sunmaktadır.
public static class ContainerBootstrapper { public static void BootstrapStructureMap() { ObjectFactory.Initialize(x => x.For<ISecurityService>().Use<SecurityService>()); } }
ContainerBootstrapper static sınıfında tanımladığımız BootstrapStructureMap metodu içerisinde interface tipine karşılık bir somut sınıf belirlenmektedir. ISecurityService interface tipi için SecurityService somut tipini kullan demiş olduk.
Hazırladığımız düzeneği çalıştırabilememiz için son olarak Global.asax içerisinde son hamlelerimizi yapmamız gerekiyor.
protected void Application_Start() { ..... .... ContainerBootstrapper.BootstrapStructureMap(); ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory()); }
Öncelikle ContainerBootstrapper.BootstrapStructureMap(); metodu ile eşleştirme işlemini gerçeklştiriyoruz. Ardından ControllerBuilder sınıfı yardımyla kendi özel conrtoller factory tipimiz olan IocControllerFactory tipini sisteme tanıtıyoruz. Artık DefaultControllerFactory sistemden çıktı ve yeni oluşturduğumuz factory tipi sistemimize dahil oldu.
Programı çalıştırdığımızda IsecurityService tipine karşılık olarak bir SecurityService nesnesi oluşturulmuştur.
StructureMap IoC container kütüphanesi hakkında detaylı bilgiyi buradan bulabilirsiniz.