Reflection: optymalizacja MemberInfo

W celu wykonania jakiegoś kodu za pomocą refleksji, należy najpierw zebrać informację o danym polu. Załóżmy, że mamy następującą klasę:

class Sample
{
    public void PrintSomething()
    {
        Console.WriteLine("Something");
    }
}

W celu wykonania metody za pomocą refleksji można:

object sample = new Sample();
MethodInfo info=sample.GetType().GetMethod("PrintSomething");
info.Invoke(sample, null);

Generalnie obiekty takie jak MemberInfo czy MethodInfo pożerają mnóstwo pamięci – są one dość ciężkie dla CLR. Klasa w końcu może mieć bardzo wiele elementów: metody, pola, zdarzenia, konstruktory, właściwości itp. Jeśli istnieje potrzeba przechowywania tego w pamięci jest to marnotrawstwo. Zwykle nie potrzebujemy tych wszystkich informacji jakie dają nam powyższe obiekty. Jeśli naszym celem jest przechowywanie MethodInfo tylko po to aby wykonać później daną operację (a nie aby dowiedzieć się czegoś więcej o danym polu), wtedy dużo lepiej jest korzystać po prostu ze wskaźnika:

object sample = new Sample();
MethodInfo heavyObject = sample.GetType().GetMethod("PrintSomething");
RuntimeMethodHandle lightObject = heavyObject.MethodHandle;

RuntimeMethodHandle zawiera jako właściwość zwykły IntPtr – wskaźnik. Jak z tego korzystać?

object sample = new Sample();
MethodInfo heavyObject = sample.GetType().GetMethod("PrintSomething");
RuntimeMethodHandle lightObject = heavyObject.MethodHandle;
MethodBase.GetMethodFromHandle(lightObject).Invoke(sample,null);

Oczywiście musimy stworzyć MemberInfo ale robimy to tylko w momencie gdy chcemy wykonać dany element. W pamięci przechowujemy wyłącznie bardzo tanie wskaźniki.Wszystkie klasy dziedziczące po MemberInfo mają swoje “tanie” odpowiedniki tzn.:

1. Type może być skonwertowany do uchwytu za pomocą statycznej metody Type.GetTypeHandle i z powrotem do typu za pomocą Type.GetTypeFromHandle:

RuntimeTypeHandle handle=Type.GetTypeHandle(typeof (Sample));
Type type = Type.GetTypeFromHandle(handle);

 

 

2. FieldInfo posiada właściwość FieldHandle, która zwraca uchwyt oraz statyczną metodę GetFieldFromHandle, która z kolei generuje ponownie FieldInfo.

FieldInfo fieldInfo;//...
RuntimeFieldHandle handle= fieldInfo.FieldHandle;
fieldInfo=FieldInfo.GetFieldFromHandle(handle);

One thought on “Reflection: optymalizacja MemberInfo”

  1. Brakuje mi w tym artykule porównania tego rozwiązania do kompilacji w locie przy pomocy Linq.Expressions.Expression. Wiadomo że kompilacja sama z siebie będzie długotrwała, natomiast wykonanie bardzo szybkie. Jednak jaki to ma wpływ na zużycie pamięci?

Leave a Reply

Your email address will not be published.