2016-08-06 8 views
-1

ランタイムメソッドをクラスメソッドにバインドしたい(ランタイムメソッドを呼び出す場合は、パラメータと戻り値の有無にかかわらず、クラスメソッドを呼び出す必要があります)。C#自動実行時にメソッドコールバックを生成しますか?

私のコードは、invokeメソッドとCallbackメソッドでパラメータを設定しないと動作しますが、パラメータを設定した場合、エラーが発生します: "エラーパラメータのカウントが一致しません。

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

カウントエラーを修正するには、、そして、あなたはまだあなたの発電機で他の問題を持って削除するか、コメントアウトあなたのforeachを誤ってパラメータのリストを移入し、ではなく

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.Emit(OpCodes.Ldarg_0); 
msilG.Emit(OpCodes.Ldarg_1); // it's cool, isn't it? 
msilG.Emit(OpCodes.Call, toCall);  

と私の上記msilG.EmitWriteLine("Hello World");を置き換える;)

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

私はちょうど最後の詳細を編集し終わった。これはテストされて動作していますので、私はあなたが*私の答えを受け入れることができることを願っています...とにかく、問題が発生したら教えてください... –

関連する問題