Factory Pattern Reflection Kullanımı .NET Design Pattern

Design Patterns(Tasarım Desenleri) arasında bana göre en işlevli, en yaygın kullanılan pattern "Factory Pattern". Uygulamamız ayağa kalktığında(runtime) kullanacağı sınıfların değişme olasılığı var ise burda "Factory Pattern" devreye girer. C# runtime instance almak için ise reflection yaygın olarak kullanılır. Reflection kullanımının yavaş olduğunuda belirtmek isterim.

Bu sebeble bunu kullanırken static nesneler ile aldığımız instance classları saklayarak tekrar kullanabiliriz. Şimdi projemizde hata durumunda farklı yerlere loglama yapmak istiyoruz diyelim. Sql'e yazarken karar değiştirdim, ufak bir değişiklik ile artık Xml'e yazsın istiyorum. Ya da Sql, Xml opsiyonlarım var iken yarın bir gün başka bir loglama yapısı geldiğinde sadece o loglama yapısının nesnesini oluşturup.

Yine ufak bir değişiklik ile çalışma anında kullanmak istiyorum. Bu classların ortak özelliğinin hepsi nedir ? Loglama yapıcak olması bu sebeble bizim loglama methodu olan bir interface class ihtiyacımız var. Ben buna arayüz diyorum. Her loglama yapısı farklı olacağından Interface tercih ediyorum, ortak bir method yapısı olsaydı eğer abstarct class kullanabilirdik. Bu interface class "ILogger" diyelim. Bundan türeyeren "SqlLogger, XmlLogger, FileLogger" adında üç tane class oluşturdum. Ve log methodunu implemente ettim.

 public interface ILogger
 {
        void Log(string value);
 }

  internal class SqlLogger : ILogger
    {
        public void Log(string value)
        {
            //Sql yazma işlemlerimi yaptım..
            Console.WriteLine("Sql'e yazıldı");
        }
    }
 internal class FileLogger : ILogger
    {

        public void Log(string value)
        {
            Console.WriteLine("Dosya'ya yazıldı");
        }
    }

 internal class XmlLogger : ILogger
    {
        public void Log(string value)
        {
            //Xml loglama işlemlerimi yaptım..
            Console.WriteLine("Xml'e yazıldı");
        }
    }

Türeyen sınıfları internal yapıyorum. Sadece bulunduğumuz assembly ulaşsın. Dışardan kullanıcak olan developer sadece bir tane "log" methodu bilsin. İçerde kim nasıl logluyor bilmesin istiyorum. Loglamanın yapılacağı yerin karar mekanizması için ise config'den "logKey" adında bir değişken ekliyorum.
Bu değişken ile beraber Factory Pattern mantığını kullanarak runtime instance alma işlemi yapacağım. Bunu yapacağım class adına "LogFactory" diyorum. Burda config'den gelen değeri okuyup ilgili logger nesnesini oluşturacağım.

 internal class LogFactory
    {
        static ILogger _logger;
        internal static ILogger GetLogger()
        {
            if (_logger == null)
            {
                string locationTypeName = System.Configuration.ConfigurationManager.AppSettings["logKey"].ToString();
		//Reflection
                Type type = Type.GetType(locationTypeName);
                _logger = (ILogger)Activator.CreateInstance(type);
            }
            return _logger;
        }
    }

Yine internal çalışıyorum. Henüz dışarıya açacağımız methodumuzu yazmadık. Burda "GetLogger" methodumuz sayesinde configden class namespace bilgisini alarak reflection yardımı ile runtime instance alıyorum ve return ediyorum.

Son olarak dışardan erişebilecek methodu yazalım. Bu loglama yapısını kullanıcak developer bu complex yapısı bilmek zorunda değil, o sadece hata geldi kardeşim logla bunu demeli. Bu yüzden ona sadece "Log" methodu sağlıycak bir sınıf yazmalıyız.

Bunun adına ben "LogManager" diyorum. LogManager içine "Log" adında bir method ekleyip developerdan string value alacağız.

 public static class LogManager
    {
        public static void Log(string value)
        {
            ILogger logger = LogFactory.GetLogger();
            logger.Log(value);
        }
    }

Artık tamamen public çalışıyorum. Kullanacağı cağıranı methodun içinde internal olarak çalıştığım "LogFactory" sınıfını kullanarak config'e yazılmış ilgili logger nesnesini instance alıp, türüyen sınıf içerisinde "Log" methodunu cağırıyorum. Geliştirme yapan developer ise bu loglama yapısını sadece aşağıdaki gibi kolayca kullanabilecek.

            try
            {

                throw new Exception();
            }
            catch (Exception ex)
            {

                LogManager.Log(ex.ToString());
            }

Görüldüğü gibi developer tek method ile işini çözüyor. Arka tarafta neler olup bittiğini öğrenmek ya da bilmek zorunda değil..

Konuyla ilgili yaptığım küçük uygulamayı burdan indirebilirsiniz. Factory Pattern Reflection Kullanimi

Yorumlar

  1. Samet ÇINAR 16.3.2016

    Teşekkür ederim Yusuf kardeşim. :)

    developers 19.3.2016

    Reflection kullanımının yavaş olduğunu söylemişsiniz peki hızlı olan nedir ne kullanılmalı ?

    Samet ÇINAR 20.3.2016

    "Dynamic Method" kullanımı reflection'a nazaran daha uğraş isteyen bir kullanım. Konuyla alakalı müsait bir vakitte detaylı bir yazı yazabilirim. Sizi mail adresinizden bilgilendiriyor olurum. @developers

Yorum Yaz