2013-02-10 8 views
5

Chciałbym emitować metodę, która ma zmienną, co mogę zrobić. Ale chciałbym zapisać w tej zmiennej obiekt MethodInfo, który jest referencją do innej (nie emitowanej) metody.Jak emitować metodę ze wstępnie załadowaną zmienną lokalną MethodInfo?

Mogłem emitować opkody, aby wywołać typeof (someClass) .GetMethod (...), ale byłoby bardziej wydajne, gdybym mógł po prostu załadować token dla tej MethodInfo i piec go bezpośrednio do zmiennej.

Tak więc, w celu przeformułowania, próbuję ustalić, czy możliwe jest jej wyemitowanie, powiedzmy, kod operacji ładowania obiektu i przekazać obiekt w czasie emisji, który zostanie załadowany na stos w czasie wykonywania. (OpCodes.Ldobj dał jakiś błąd, gdy próbowałem tego). Czy jestem zmuszony do wysyłania opkodów, które wykonają to w czasie wykonywania?

+0

Myślę, że to możliwe. Eric Lippert kiedyś blogował o możliwym informatorze C#, który by to wykorzystał. – usr

+0

Czy możesz podać trochę kontekstu z powodu, aby problem był dla mnie/dla nas bardziej przejrzysty? –

+0

@usr [Artykuł, o którym mówisz] (http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx) jest o składniowych problemach 'infoof', a nie o tym, jak można to zaimplementować. – svick

Odpowiedz

8

Nie można po prostu załadować żadnego ogólnego obiektu w IL, ponieważ nie ma sposobu na zapisanie go w IL (z wyjątkiem niektórych specjalnych typów, takich jak string). Można obejść to przy użyciu serializacji (dla typów, które ją obsługują), ale nie sądzę, że tego właśnie chcesz. Ponadto, ldobj ma zupełnie inny cel.

Ale możesz to zrobić dla MethodInfo w sposób bardzo podobny do tego, co C# robi dla operatora typeof. Oznacza to, że:

  1. pomocą instrukcji ldtoken aby uzyskać RuntimeMethodHandle
  2. nazywając MethodBase.GetMethodFromHandle() dostać MethodBase
  3. miotać MethodInfo

cały kod, aby wygenerować metodę, która zwraca MethodInfo może wyglądać tak:

MethodInfo loadedMethod = …; 
var getMethodMethod = typeof(MethodBase).GetMethod(
    "GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) }); 

var createdMethod = new DynamicMethod(
    "GetMethodInfo", typeof(MethodInfo), Type.EmptyTypes); 

var il = createdMethod.GetILGenerator(); 
il.Emit(OpCodes.Ldtoken, loadedMethod); 
il.Emit(OpCodes.Call, getMethodMethod); 
il.Emit(OpCodes.Castclass, typeof(MethodInfo)); 
il.Emit(OpCodes.Ret); 

var func = (Func<MethodInfo>)createdMethod.CreateDelegate(typeof(Func<MethodInfo>)); 
Console.WriteLine(func()); 
+0

Działa doskonale! –

Powiązane problemy