2015-11-08 45 views
0

我試圖從接口創建一個代理類。在方法中,我只想收集對象數組中的所有參數並傳遞給已知的方法。所以我設法讓它在沒有參數和返回類型的情況下工作。只要我嘗試創建我的數組,我會得到「其他信息:公共語言運行時檢測到一個無效的程序。」..真的不知道如何從這裏調試和IL代碼似乎是正確的(?)。Reflection.Emit實現接口並創建數組IL

public class Program 
{ 
    static void Main(string[] args) 
    { 
     var v = CreateProxy<IFoo>(); 
     v.DoSomething(); 
    } 

    public static void TheMethod(object[] args) 
    { 

    } 

    public interface IFoo 
    { 
     void DoSomething(); 
    } 

    public static T CreateProxy<T>() 
    { 
     var interfaceType = typeof(T); 

     AssemblyName assemblyName = new AssemblyName(string.Format("tmp_{0}", interfaceType.FullName)); 
     string moduleName = string.Format("{0}.dll", assemblyName.Name); 
     string ns = interfaceType.Namespace; 
     if (!string.IsNullOrEmpty(ns)) 
      ns += "."; 

     var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave); 
     var module = assembly.DefineDynamicModule(moduleName, false); 
     var type = module.DefineType(String.Format("{0}Proxy_{1}", ns, interfaceType.Name), TypeAttributes.Class | TypeAttributes.AnsiClass |TypeAttributes.Sealed |TypeAttributes.NotPublic); 
     type.AddInterfaceImplementation(interfaceType); 

     //Constructor 
     var ctor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] {}); 
     var generator = ctor.GetILGenerator(); 
     generator.Emit(OpCodes.Ret); 

     //Methods 
     foreach (var method in interfaceType.GetMethods()) 
     { 
      var args = method.GetParameters(); 
      var methodImpl = type.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, (from arg in args select arg.ParameterType).ToArray()); 
      generator = methodImpl.GetILGenerator(); 

      generator.Emit(OpCodes.Nop); 
      generator.Emit(OpCodes.Ldc_I4_1); 
      generator.Emit(OpCodes.Newarr, typeof(object)); 
      generator.Emit(OpCodes.Stloc_0); 
      generator.Emit(OpCodes.Ldloc_0); 
      generator.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof(Program.TheMethod))); 
      generator.Emit(OpCodes.Nop); 

      generator.Emit(OpCodes.Ret); 
     } 

     return (T)Activator.CreateInstance(type.CreateType()); 
    } 

} 

即時嘗試發射的方法應該看起來像這樣。

public void DoSomething() 
    { 
     object[] arr = new object[1]; 
     Program.TheMethod(arr); 
    } 

我在這裏錯過了什麼?

+0

其靜態的?不需要一個實例? – Evelie

回答

3

你應該初始化當地人:

foreach (var method in interfaceType.GetMethods()) 
{ 
    var args = method.GetParameters(); 
    var methodImpl = type.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, (from arg in args select arg.ParameterType).ToArray()); 
    generator = methodImpl.GetILGenerator(); 

    generator.DeclareLocal(typeof(object[])); 

    .... 
    ....