2010-08-19 1 views
0

Возможно ли это?Использование свойства Method Method в действии <T> делегат в il.EmitCall

// 
// create a delegate 
Action<Type> action = (t) => t.DoSomething; 

// 
// get the IL generator for a method 
ILGenerator il = myMethodBuilder.GetILGenerator(); 

// 
// try and call the delegate 
il.EmitCall(OpCodes.Callvirt, action.Method, null); 

Im get MethodAccessException всякий раз, когда я пытаюсь вызвать метод.

Благодаря

ответ

3

Im получая MethodAccessException всякий раз, когда я пытаюсь вызвать метод.

Это связано с тем, что метод, сгенерированный для лямбда C# (t) => t.DoSomething, является закрытым. Скорее всего, эта лямбда не будет статичной, в зависимости от того, какая из локальных переменных она захватывает из внешнего метода. Вы выдаете инструкцию callvirt, но, похоже, вы не поставляете экземпляр.

Вы можете это проверить, загрузив код приложения в Reflector и посмотрев на реализацию вашей ёмкости (t) => t.DoSomething.

Вам нужно либо:

  • Улучшайте лямбду к реальному public static методу в внешне видимом классе
  • Найти способ включить параметр типа Action<Type> в вашем методе IL, генерировать код, называет Action<Type>.Invoke, а затем передать вашу action переменную в сгенерированный метод
+0

Я вижу, что MethodInfo IsPrivate имеет значение true, есть ли способ изменить это? В противном случае я могу просто использовать открытый статический член, но его опрятный с Lambda :) Спасибо –

+0

Невозможно изменить это; это деталь реализации компилятора C# –

+1

Если учесть это, лучшим вариантом может быть поиск способа передачи делегата 'action' в ваш сгенерированный метод либо путем добавления параметра, либо путем создания вашего сгенерированного метода экземпляром класса член и установив поле в этом классе. Поскольку вы будете называть свою лямбду через делегата, вы не будете чувствительны к тому, как эта лямбда реализована. –

0

Если вы используете динамический метод, вы можете использовать проверки видимости пропуска в дрожании.