2013-02-24 1 views
1

Я пытаюсь создать deleagte для вызова статического универсального метода. Но я получил ошибку: обнаружен неверный код! nyone идея, что не так с моим IL?Вызывать статический общий метод через делегата через Emit

Идентификатор FindStaticMethod в коде примера работает и возвращает информацию о методе с заданными аргументами типа!

public delegate object GenericStaticInvoker(params object[] arguments); 

public static GenericStaticInvoker GenericMethodInvokerStaticMethod(Type type, string methodName, Type[] typeArguments, Type[] parameterTypes) 
    { 
     MethodInfo methodInfo; 
     ParameterInfo[] parameters; 

     // find the method to be invoked 
     FindStaticMethod(type, methodName, typeArguments, parameterTypes, out methodInfo, out parameters); 

     string name = string.Format("__MethodInvoker_{0}_ON_{1}", methodInfo.Name, methodInfo.DeclaringType.Name); 

     DynamicMethod dynamicMethod; 
     dynamicMethod = new DynamicMethod(name, typeof(object), new Type[] { typeof(object[]) }, methodInfo.DeclaringType); 

     ILGenerator generator = dynamicMethod.GetILGenerator(); 

     // define local vars 
     if (methodInfo.ReturnType != typeof(void)) 
      generator.DeclareLocal(methodInfo.ReturnType); 

     for (int i = 0; i < parameters.Length; i++) 
     { 
      // load paramters they are passed as an object array 
      generator.Emit(OpCodes.Ldarg_1); 

      // load array element 
      generator.Emit(OpCodes.Ldc_I4, i); 
      generator.Emit(OpCodes.Ldelem_Ref); 

      // cast or unbox parameter as needed 
      Type parameterType = parameters[i].ParameterType; 
      if (parameterType.IsClass) 
      { 
       generator.Emit(OpCodes.Castclass, parameterType); 
      } 
      else 
      { 
       generator.Emit(OpCodes.Unbox_Any, parameterType); 
      } 
     } 

     // call method 
     generator.EmitCall(OpCodes.Call, methodInfo, null); 

     // handle method return if needed 
     if (methodInfo.ReturnType == typeof(void)) 
     { 
      // return null 
      generator.Emit(OpCodes.Ldnull);     
      generator.Emit(OpCodes.Ret); 
     } 
     else 
     { 
      // box value if needed 
      if (methodInfo.ReturnType.IsValueType) 
      { 
       generator.Emit(OpCodes.Box, methodInfo.ReturnType); 
      } 

      // store to the local var 
      generator.Emit(OpCodes.Stloc_0); 

      // load local and return 
      generator.Emit(OpCodes.Ldloc_0); 
      generator.Emit(OpCodes.Ret); 
     } 



     // return delegate 
     return (GenericStaticInvoker)dynamicMethod.CreateDelegate(typeof(GenericStaticInvoker)); 
    } 
+0

Мне нужен этот точный код, любой шанс, что вы обновите свой вопрос w с рабочим решением? –

ответ

1
  • В методе экземпляра, «этот» параметр может быть загружен в стек оценки по Ldarg_0 и затем «фактические» параметры могут быть загружены с Ldarg_ {х} (с х 1 через N).

  • Если у вас есть статический метод (также случай любой лямбда, будь то отражение или нет), «фактические» параметры могут быть загружены с помощью Ldarg_ {x} (с x 0 по N-1).

  • Чтобы обернуть все это для общего случая: эта «эта» ссылка является параметром в своем собственном праве. Его отсутствие не оставляет пустого слота в стеке (ldarg.0 будет использоваться и должен использоваться для первого параметра «этого»).

Так что в вашем конкретном случае, вы не можете использовать OpCodes.Ldarg_1 загружаем ваши PARAMS объект [] Параметры уникальный параметр:

// ...etc... 
for (int i = 0; i < parameters.Length; i++) 
{ 
    // load paramters they are passed as an object array 
    generator.Emit(OpCodes.Ldarg_1); 

    // ...etc... 

Вы должны использовать OpCodes.Ldarg_0:

// ...etc... 
for (int i = 0; i < parameters.Length; i++) 
{ 
    // load paramters they are passed as an object array 
    generator.Emit(OpCodes.Ldarg_0); 

    // ...etc... 
+0

Я проверяю это завтра, спасибо! –

 Смежные вопросы

  • Нет связанных вопросов^_^