Date Image Thursday, November 29, 2012 | Kategoriler | C#, Linq, Tümü

Linq Expression İle MethodInfo'nun Elde Edilmesi Ve Method Attribute Kullanımı

Reflection işlemleri ile uğraşırken kullanılan sınıflardan biri de MethodInfo sınıfıdır. Elimizde tipini bilmediğimiz bir nesne vardır ve bu nesne içinde varolduğunu bildiğimiz bir metodu çalıştırmak isteyebiliriz. Bu durumda bu nesne tipi içinde reflection yardımıyla GetMethod metodunu çağırarak parametre olarak metodun ismini geçtiğimizde bize MethodInfo tipinde bir nesne döner. Bu nesne içerisinde o metotla ilgili bilgiler bulunur.Invoke metodunu çağırarak metodu çalıştırabiliriz ya da sınıf içerisindeki diğer metot ve propertyleri kullanarak işlemler yapabiliriz.

Tipini bilmediğimiz bir nesne üzerinde bir metodun nasıl yakalanacağı ve nasıl çalıştırılabileceği hakkında çok basit ve kısa olarak teorik bilgiyi yukarıda verdim. Konumuz bu olmadığı için ne kadar kısa olursa o kadar iyi :). Şimdi, belli bir tipe ait metotları linq sorguları ile(lambda expression kullanarak) nasıl elde edebileceğimize bakacağız. Ayrıca, örnek olarak oluşturacağımız metot için custom bir attribute tanımlayıp MethodInfo nesnesi içerisinden bunu da görüntüleyeceğiz.

    public static class ReflectionHelper
    {
        public static MethodInfo GetMethodInfo
(Expression> methodInfoExpression)
        {
            return GetMethodInfo((LambdaExpression)methodInfoExpression);
        }

        private static MethodInfo GetMethodInfo(LambdaExpression methodInfoExpression)
        {
            MethodCallExpression methodInfoExpressionBody = methodInfoExpression.Body as MethodCallExpression;

            if (methodInfoExpressionBody != null)
            {
                return methodInfoExpressionBody.Method;
            }
            else
            {
                return null;
            }
        }
    }

Öncelikle ReflectionHelper adında bir helper sınıf oluşturduk ve bu sınıf içerisine GetMethodInfo adında iki metot yazdık. Bunlardan birincisi public ve lambda expression ile sorgulanabilecek bir yapıda.Kendi içerisinde ise private olan GetMethodInfo metodunu çağırıyor ve burada gelen expressionın bodysi MethodCallExpression tipine cast edilerek MethodInfo tipindeki Method propertysi geri dönülüyor.

MethodInfo'yu veren generic metotları yazdığımıza göre bunları kullanmanın vakti gelmiş demektir.Console uygulamasında Main metodumuz içerisinde ReflectionHelper yardımcı sınıfımızdan faydalanarak EmptyMethod adındaki metodumuzun Info bilgisini alacağız. Burada aynı sınıf içindeki metodun bilgisini almamızın pek bir anlamı yok sadece bilgi amaçlı kullanım için bunu yapacağız. Yoksa normal şartlarda Account gibi bir sınıfımız olabilir ve bu sınıfın içerisinden GetAccountInfo gibi bir metodu çağırmak isteyebiliriz ya da bu metoda tanımlanan attributelere bakarak işlemler yapabiliriz. Örneğin bu metodun çalıştırıldığında loglanmasını istiyor olabiliriz başka bir metodun ise loglanmasını istemeyebiliriz. Bu durumda metoda tanımlayacağımız bir attribute içindeki LogingEnabled gibi bir property yi true ve ya false set ederek loglama durumunu belirtebiliriz. Bir method invoker ımız var ise bu method invoker içerisinde metodu invoke etmeden önce attribute lerine bakıp ona göre karar vermesini sağlayabiliriz.

Aşağıda Program sınıfımızdaki EmptyMethod metodunu nasıl aldığımızı göreceksiniz. Lambda expression ile Program sınıfını p ile temsil ederek EmptyMethod çağrımı yapar gibi yazıyoruz ve geriye MethodInfo nesnemiz dönüyor. Sonrasında GetCustomAttributes metodu ile bu metoda tanımlanmış olan custom attributeleri alıyoruz ve bu koleksiyonda foreach ile dönüyoruz. Bu döngü içerisinde MethodAttribute tipindeki attributeleri yakalayarak ToString ile bilgisini console a yazdırıyoruz.

    class Program
    {
        static void Main(string[] args)
        {
            MethodInfo methodInfo = ReflectionHelper.GetMethodInfo
(p => p.EmptyMethod());

            object[] methodAttributes = methodInfo.GetCustomAttributes(true);
            foreach (object att in methodAttributes)
            {
                if (att is MethodAttribute)
                {
                    MethodAttribute attribute = att as MethodAttribute;
                    if (attribute.Enabled)
                    {
                        Console.WriteLine(attribute.ToString());
                    }
                }
            }
            Console.ReadKey();
        }

        [MethodAttribute(Enabled = true, Author = "Serdar Sert", Company = "Anonim Şirket", IsTransactional = false)]
        public string EmptyMethod()
        {
            return String.Empty;
        }
    }

Yukarıda kullandığımız MethodAttribute sınıfı aşağıdaki gibidir.Attribute base alınarak istediğimiz propertyleri ekliyoruz.

    public class MethodAttribute : Attribute
    {
        public bool Enabled { get; set; }
        public string Author { get; set; }
        public string Company { get; set; }
        public bool IsTransactional { get; set; }

        public override string ToString()
        {
            return String.Format(@"
            [MethodAttribute] 
                Enabled = {0} 
                Author = {1} 
                Company = {2}
                IsTransactional = {3}",
                Enabled, Author, Company, IsTransactional);
        }
    }
    

Bu işlemler sonrasında Console uygulamasını çalıştırdığımızda, methodInfo nun alındığını ve attribute un bulunarak ToString metodunun çağrıldığını görüyoruz.Sonuç olarak metoda tanımladığımız attribute'teki değerler ekrana basılıyor. Basit ve kısa olarak anlatmak istediğim bu konu umarım daha gelişmiş uygulamalar için başlangıç noktası olabilir.

[MethodAttribute]
Enabled = True
Author = Serdar Sert
Company = Anonim Şirket
IsTransactional = False

Etiketler : C# , Linq , Expression , Console , Reflection