2016-08-06 4 views
-1

Я хочу привязать метод выполнения к методу класса (если я вызываю метод runtime, он должен вызывать метод класса, с параметрами или без параметров и возвращаемым значением).C# Автоматический вызов метода генерации метода во время выполнения?

Мой код работает, если я не устанавливаю параметр для метода вызова и метода обратного вызова, но, если я задаю параметры, я получил ошибку: «дать ошибку« Несоответствие счетчика параметров ».: Как я могу ее исправить?

public class RunNow 
{ 
    public void Run(string hoo) 
    { 

    } 

    public void Callback(string ali) 
    { 
     Console.WriteLine("yessss"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     RunNow run = new CSMethodInjection.RunNow(); 
     var methodToCall = run.GetType().GetMethod("Callback"); 
     var t = GenerateType(run.GetType().Name, methodToCall); 
     if (t != null) 
     { 
      object o = Activator.CreateInstance(t); 
      MethodInfo helloWorld = t.GetMethod(methodToCall.Name); 
      if (helloWorld != null) 
      { 
       helloWorld.Invoke(o, new object[] { "aaaaa" });//give error Parameter count mismatch. 
      } 
     } 
     Console.ReadLine(); 
    } 

    static Type GenerateType(string className, MethodInfo toCall) 
    { 
     AppDomain currentDomain = AppDomain.CurrentDomain; 
     AssemblyName assemName = new AssemblyName(); 
     assemName.Name = "InjectionAssembly"; 

     AssemblyBuilder assemBuilder = currentDomain.DefineDynamicAssembly(assemName, AssemblyBuilderAccess.Run); 

     ModuleBuilder moduleBuilder = assemBuilder.DefineDynamicModule("InjectionModule"); 

     TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public); 
     MethodBuilder methodBuilder = typeBuilder.DefineMethod(toCall.Name, MethodAttributes.Public, null, null); 
     List<Type> parameters = new List<Type>(); 
     foreach (var item in toCall.GetParameters()) 
     { 
      parameters.Add(item.ParameterType); 
      var pBuilder = methodBuilder.DefineParameter(item.Position, item.Attributes, item.Name); 

     } 

     if (parameters.Count > 0) 
      methodBuilder.SetParameters(parameters.ToArray()); 
     methodBuilder.SetReturnType(toCall.ReturnType); 
     ILGenerator msilG = methodBuilder.GetILGenerator(); 
     msilG.Emit(OpCodes.Ldarg_0); 
     msilG.Emit(OpCodes.Call, toCall); 
     msilG.Emit(OpCodes.Ret); 
     return typeBuilder.CreateType(); 
    } 
} 
+0

Не могли бы вы попробовать мой ответ? Пожалуйста, ** отредактируйте ** свой вопрос, чтобы сообщить мне, если у вас все еще есть проблемы, ** после ** применения изменений кода, которые я предложил ниже. спасибо за ваше внимание :) –

+0

спасибо за ответ, что это работает :) –

ответ

0

Чтобы исправить ошибку подсчета, вы можете удалить или закомментировать ваш Еогеасп ошибочно Наполнение список параметров исделать вместо

MethodBuilder methodBuilder = typeBuilder.DefineMethod(toCall.Name, 
    MethodAttributes.Public, 
    toCall.ReturnType, 
    toCall.GetParameters().Select(x => x.ParameterType).ToArray()); 

Тогда вы по-прежнему есть и другие проблемы в вашем генераторе, мы можем упростить его следующим образом:

ILGenerator msilG = methodBuilder.GetILGenerator(); 
msilG.EmitWriteLine("Hello World"); // or much better see below 
msilG.Emit(OpCodes.Ret); 
return typeBuilder.CreateType(); 

или намного лучше заменить мой выше msilG.EmitWriteLine("Hello World"); с

msilG.Emit(OpCodes.Ldarg_0); 
msilG.Emit(OpCodes.Ldarg_1); // it's cool, isn't it? 
msilG.Emit(OpCodes.Call, toCall);  

, наконец, вы можете также адаптировать функцию обратного вызова;)

public void Callback(string ali) 
{ 
    Console.WriteLine(ali); // let me see "aaaaa" 
} 
+0

Я только что закончил редактирование последних деталей. Это проверено и работает, поэтому я надеюсь, что вы можете * принять * мой ответ ... в любом случае, дайте мне знать, если возникнут какие-либо проблемы ... –

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