Создать DynamicMethod из MethodInfo - PullRequest
2 голосов
/ 23 июня 2010

Я просматривал статью Джоэла Побара Dodge Common Pidfall для создания скоростных приложений , посвященную Reflection, и я смотрел на определенный фрагмент кода, который не компилируется (слегка измененный, чтобы сузить конкретная ошибка, потому что в его примере было больше ошибок):

MethodInfo writeLine = typeof(Console).GetMethod("WriteLine");
RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
DynamicMethod dm = new DynamicMethod(
    "HelloWorld",          // name of the method
    typeof(void),          // return type of the method
    new Type[]{},          // argument types for the method
    false);                // skip JIT visibility checks

ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello, world");
il.Emit(OpCodes.Call, myMethodHandle); // <-- 2 errors here
il.Emit(OpCodes.Ret);

Ошибки:

Program.cs(350,13): error CS1502: The best overloaded method match for 'System.Reflection.Emit.ILGenerator.Emit(System.Reflection.Emit.OpCode, byte)' has some invalid arguments
Program.cs(350,35): error CS1503: Argument '2': cannot convert from 'System.RuntimeMethodHandle' to 'byte'

ILGenerator может Emit с MethodInfo, но, похоже, он не поддерживает MethodHandle ... кто-нибудь знает, как заставить этот образец работать?

Ответы [ 2 ]

3 голосов
/ 23 июня 2010

Как и так?

        MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new Type[] {typeof(string)});
        RuntimeMethodHandle myMethodHandle = writeLine.MethodHandle;
        DynamicMethod dm = new DynamicMethod(
            "HelloWorld",          // name of the method
            typeof(void),          // return type of the method
            new Type[] { },          // argument types for the method
            false);                // skip JIT visibility checks

        ILGenerator il = dm.GetILGenerator();
        il.Emit(OpCodes.Ldstr, "Hello, world");
        il.EmitCall(OpCodes.Call, writeLine, null);
        il.Emit(OpCodes.Ret);
        // test it 
        Action act = (Action)dm.CreateDelegate(typeof(Action));
        act();

Изменения:

  • Я использовал твик GetMethod, чтобы найти перегрузку (string) (в противном случае это неоднозначное совпадение)
  • используйте MethodInfo, а не дескриптор (так как этого хочет ILGenerator)
  • используйте EmitCall (другой тоже мог бы сработать, но я знаю этот способ работает)
0 голосов
/ 04 марта 2014

С помощью этой библиотеки на Nuget.org: ClassWrapper

Он создает оболочки для типов, которые внутренне используют динамически генерируемые методы.Поэтому отражение не используется (только в метод ClassWrapperDescriptor.Load для генерации динамических выражений)

Дано, например, класс с именем SampleClass

//Create the class wrapper descriptor, this can be cached and reused!
var classWrapperDescriptor = new ClassWrapperDescriptor(typeof(SampleClass));
//Initialize the descriptor
classWrapperDescriptor.Load();

//Create the instance of our object
object instance = new SampleClass();

//Create an instance of the wrapper
var classWrapper = classWrapperDescriptor.CreateWrapper(instance);

//Set a property
classWrapper.Set("StringProperty","test");

//Get a property
var stringPropertyValue = classWrapper.Get<string>("StringProperty");

//Invoke a method without return statement
classWrapper.Invoke("ParamMethod", "paramValue");

//Invoke a method witho return statement
var result = classWrapper.Invoke<int>("ReturnMethod", "paramValue");

Любая обратная связь с этой библиотекой действительно приветствуется!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...