21.08.2017

C# Castle Windsor ve IoC Container Kullanimi

IoC Container

Bu makale de ise olayi bir kademe daha ileriye tasiyacagiz. Bir önceki makale dependency injection da isi yürütecek ve bundan önce instance alma islemini yapacak kismi bir metotda yapiyorduk. Böyle bir yapida ise, söz konusu tipe isimiz her düstügünde bir instance daha alinacak ve ayni islemler tekrarlanacak.
Oysaki IoC Container'lar sayesinde, instance islemini bir kerelige mahsus yaptirabilir ve tipi kullanacagimiz her bir islemde ise bir önceki instancenin kullanilmasini saglayabiliriz.

Envarterlerin Indirilmesi

Su anda yapacagimiz islemlere karar verdik. Sira sorunumuzu çözecek babayigit bir IoC kütüphanesi bulmakta. Aklima ilk gelen Microsoft ürünü olan, Ninject ve Castle Projects adi altinda gelistirilen Windsor kütüphanesi.

Bu makalemde Windsor kütüphanesini kullaniyor olacagiz. Tabi ki kodlama kismina geçmeden önce kütüphanemizin en son sürümünü buradan indirelim.
Indirdigimiz dosya içerisinden Castle.Core ve Castle.Windsor kütüphanelerini projemize ekleyelim.

Mouse ve Base Tiplerimiz

Hatirlarsaniz bir önceki makalede son olarak bir adet IMouse adinda bir interfaceimiz ve bu interfaceyi implemente eden iki farkli mouse tipimiz mevcuttu. Toplam da bu 3 tipi yeni projemiz de yine kullaniyor olacagiz. Bu nedenle asagidaki tipleri projemize dahil edelim.

?

1

2

3

4

interface IMouse

    {

        void Write();

    }

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class LogitechMouse : IMouse

    {

        public void Write()

        {

            Console.WriteLine("Logitech Mouse Kullanildi");

        }

    }

 

    class A4TechMouse : IMouse

    {

        public void Write()

        {

            Console.WriteLine("A4Tech Mouse Kullanildi");

        }

    }

Windsor Container ve Util Sinifimiz

Yukarida kullanilacak tüm tiplerimizin, bir container içerisinde bekletileceginden bahsetmistik. Böylece tip ile ilgili bir islem yapacagimizda ne bir daha instance almak için ugrasagicaz. Ne de hangi tipin kullanilacagina karar vermek için ugrasacagiz. Bu sayede uygulama akisinin, runtime aninda degistirilmesini saglamis olacagiz.

Bunun için IoC adinda bir adet static sinif yazalim. Sinifimizin kodlari asagidaki gibi olacaktir;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public static class IoC

    {

        private static readonly IWindsorContainer container = new WindsorContainer();

 

        public static void A4TechFactory()

        {

            container.Register(

                Component.For<IMouse>().ImplementedBy<A4TechMouse>()

                );

        }

 

        public static void LogitechFactory()

        {

            container.Register(

                Component.For<IMouse>().ImplementedBy<LogitechMouse>()

                );

        }

 

        public static T ResolveMouse<T>()

        {

            return container.Resolve<T>();

        }

    }

Yukaridaki kodda deginmek istedigim ilk kisim container adli degiskenimiz. Iste tüm instanceleri içerisinde tutacak ve gerektiginde dogru tipi bize ulastiracak nesne tam olarak burada. IWindsorContainer interfaceini implemente eden WindsorContainer adli siniftan bir adet instance aliyoruz. Static sinif içerisinde çalismamizi sürdürdügümüz içinde nesnemiz singleton yapida olacaktir.

Tabi ki bir üst katmanda yani IoC sinifini kullanarak mouse tiplerinden birini elde etmek isteyen kisima dogru tipi verebilmek için öncelikle container içerisinde bu tiplerin kaydedilmesi gerekmektedir. Bunun için iki farkli mouse tipinide kayit edecek iki farkli metot yaziyoruz.

LogitechFactory adli metot IMouse interfaceini implemente eden LogitechMouse adli siniftan bir adet instance alinmasini ve container içerisine eklenmesini saglarken, A4TechFactory de ayni islemi A4TechMouse tipi için yapmaktadir.

Bunu sözlü olarakta ifade etmemiz mümkün. Yani LogitechFactory metodu tetiklendiginde container sunu düsünmekte ; "Benden IMouse tipi için bir istek gelirse, LogitechMouse tipini geri gönderecegim"

Su anda tiplerimizin kaydedilmesini sagladik. Bir de kaydedilen tipe ulasilmasini saglayacak bir metot yazmaliyiz. Aslinda IWindsorContainer interfacesi Resolve adli bir metot içermektedir. Bu metoda gönderilecek bir generic tip, container içerisinden seçilip geri gönderilir. Fakat container nesnesini private olarak tanimladigimiz için bu metoduda çagiracak baska bir metod yazmaliyiz. Bunun içinde ResolveMouse adli metodu kullanacagiz.

Tiplerin Kaydedilmesi ve Kullanilmasi

Su anda tiplerin kaydedilmesini ve kaydedilen tipin seçilip, geri getirilmesini saglayacak tüm metotlari yazdik. Simdi ise projeyi deneyecegimiz console applicationin main metodunu tasarlayalim. Aslinda bakacak olursak çokta fazla bir kod yazmayacagiz. Çünkü az önce yazdigimiz IoC sinifi tüm islemlerimizi harika bir sekilde gerçeklestirecektir.

Tek yapmamiz gereken hangi mouse tipini kullanacaksak, o tip için yazdigimiz factory metodunu tetiklemek ve program akista iken tipi Resolve ederek içerisindeki Write metodunu tetiklemek olacaktir.
LogitechMouse tipi için asagidaki kodu deneyebilirsiniz;

?

1

2

3

4

5

6

7

8

9

class Program

    {

        static void Main(string[] args)

        {

            IoC.LogitechFactory();

 

            IoC.ResolveMouse<IMouse>().Write();

        }

    }

Yukaridaki kod ile öncelikle IMouse tipini baz alarak LogitechMouse tipinde bir adet instance alinacak ve alinan instance container'a eklenecektir.
Ardindan gelen Resolve metodu ile container içerisinde IMouse tipi için kaydedilmis instance alinacak ve içerisindeki Write metodu tetiklenecektir.