2016-08-06 7 views
-1

런타임 메서드를 클래스 메서드에 바인딩하려고합니다 (런타임 메서드를 호출하면 매개 변수 및 반환 값의 유무에 관계없이 클래스 메서드를 호출해야합니다).런타임시 자동으로 메서드 콜백을 생성합니까?

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

당신이 내 대답을 시도 할 수)또는 훨씬 더, 내 위의 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); 

당신은 또한 콜백을 적용 할 수 있습니다로 교체? ** 아래에 제안한 코드 변경 사항을 적용한 후에도 ** 문제가 지속될 경우 ** 귀하의 질문을 ** 수정하여 ** 알려주십시오. 고마워요. 고마워. –

+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(); 
public void Callback(string ali) 
{ 
    Console.WriteLine(ali); // let me see "aaaaa" 
} 
+0

마지막 세부 사항 편집을 마쳤습니다. 이것은 테스트를 거쳐 작동합니다. 그래서 제 대답을 받아 들일 수 있기를 바랍니다. 어쨌든 어떤 문제가 발생하면 알려주세요. –