Reflection.Emit для динамического создания метода

Я хотел бы создать динамически некоторый метод, который будет принимать один параметр - экземпляр класса A, а затем будет выполнять метод B в переданном экземпляре A. B имеет параметр типа int. Итак, вот схема:

dynamicMethod(A a){
a.B(12);
}

Вот что я пробовал:

DynamicMethod method = new DynamicMethod(string.Empty, typeof(void), new[] { typeof(A) }, typeof(Program));
MethodInfo methodB = typeof(A).GetMethod("B", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
ILGenerator gen = method.GetILGenerator();

gen.Emit(OpCodes.Nop);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_S, 100);
gen.Emit(OpCodes.Call, methodB);

Но компилятор говорит мне, что CLR не нашла метод. Не могли бы вы помочь мне с этим?


person Pavel Podlipensky    schedule 06.09.2009    source источник
comment
Вместо этого вы можете использовать System.Linq.Expressions для компиляции дерева выражений. Это легче.   -  person mmx    schedule 06.09.2009


Ответы (1)


MSDN о параметре types функции Type.GetMethod:

Массив объектов Type, представляющий количество, порядок и тип параметров, которые должен получить метод.

Вы передаете пустой массив, который указывает на "метод, не принимающий параметров". Но, как вы сказали, «B имеет [a] параметр типа int».

Это будет работать:

MethodInfo methodB = typeof(A).GetMethod(
            "B",
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
            null,
            new Type[] { typeof(int) }
            , null);

Если я правильно понимаю, Ldarg_S будет загрузите сотый аргумент вашего метода, аналогично Ldarg_0:

gen.Emit(OpCodes.Ldarg_S, 100);

Для загрузки постоянного значения используйте Ldc_I4

gen.Emit(OpCodes.Ldc_I4, 100);
person weiqure    schedule 06.09.2009
comment
Да, верно, но как передать этот параметр через метод Emit? Какой OpCode следует использовать? - person Pavel Podlipensky; 06.09.2009