26 Ekim 2015 Pazartesi

Reflection ile Metod Çağırmak

Giriş
Java'da kullanılan Method sınıfı ile C#'ta kullanılan MethodInfo sınıfları birbirlerine çok benziyorlar. Her ikisi de bir class/type sınıfı tarafından döndürülüyorlar.

Her iki dilde de  Metod/MethodInfo nesnesini bulmak için metod ismi ve varsa metodun aldığı parametre tipleri kullanılır. Daha Metod/MethodInfo nesnesinin invoke/Invoke fonksiyonu çağırılarak metod çalıştırılır.

Java
Aşağıdaki gibi static metodlar içeren bir sınıf olsun
class VendorApi {
    static void func1(char x) {}
    static void func1(int x) {}
    static void func1(float x) {}
    static void func1(double x) {}
}
Bu sınıfın metodlarını generic bir veri yapısına yerleştirebilirim. Dikkat edilirse doğru metodu bulmak için func1 metod ismi yanında metodun imzasındaki diğer parametreleri de vermem gerekiyor.
Map<Class<?>, Method> mapping = new HashMap<>();
mapping.put(Integer.class, VendorApi.class.getMethod("func1", int.class));
Bu metodu çağırmam için şöyle bir kod parçası yeterli. invoke metodunun ilk parametresi metodumuz static olduğu için null oluyor.
static void callVendorFunc(Object arg) {   // no need for generics here
    mapping.get(arg.getClass()).invoke(null, arg);
}
Şimdi metodun nasıl bulunduğuna bakalım.

Class.getMethod 
Bu metod ile kalıtımla gelen veya sınıfın için tanımlanmış olan tüm public method'lara erişilebilir. Örnek:
file.getClass().getMethod("doStuff").invoke(file);
private erişimi ile tanımlanmış bazı iç sınıfların metodlarına erişmek istenirse
IllegalAccessException alınabilir. Bu gibi durumlarda yapılması gereken setAccessible (true) yöntemi ile reflection ile elde edilen Method sınıfını erişilebilir kılmaktır.

Class.getDeclaredMethod
Bu metod ile sınıfa ait public veya non-public tüm Method'lara erişilebilir.

C#
1. Önce Type nesnesini bul
2. Type.GetMethod ("MethodName") ile MethodInfo nesnesini al
3. MethodInfi.Invoke (object,parametreler) ile metodu çağır.

Static Metod Çağırma
Aşağıdaki gibi static metod içeren bir sınıf olsun
static class Foo
{
    public static String Bar() { return "Bar"; }
}
Bu sınıfın metodunu çağırmak için şöyle yaparız. Metod static olduğu için ve parametre almadığı için Invoke(null,null) olarak çağrılıyor.
Type type = Type.GetType("Foo");
MethodInfo info = type.GetMethod("Bar");
Console.WriteLine(info.Invoke(null, null));
Public Metod Çağırma
Sadece public olan bir metod da benzer şekilde çağrılır. Ancak bu sefer Invoke(object,parametre) şeklinde kullanıyoruz.
//Your class
public class MyClass 
{
    public class CustomColor 
    {
        public int h;
        public int s;
        public int v;
    }

    public string[] ConvertColors(List<CustomColor> colors)
    {
        return new string[]{"1"};
    }
}

//Usage
MyClass mc = new MyClass();
MyClass.CustomColor cc = new MyClass.CustomColor();

Type t = mc.GetType();
MethodInfo mi = t.GetMethod("ConvertColors");
List<MyClass.CustomColor> lst = new List<MyClass.CustomColor>
{   
  new MyClass.CustomColor(),
  new MyClass.CustomColor()
};
var x = (string[])mi.Invoke(mc,new object[]{lst});
Console.WriteLine (x.Count());




Hiç yorum yok:

Yorum Gönder