Reflection.Emit 实现接口并创建数组 IL

Reflection.Emit Implement interface and create array IL

我正在尝试从界面创建代理 Class。在方法中,我只想收集对象数组中的所有参数并传递给已知方法。所以 faar 我设法让它在没有参数和 return 类型的情况下工作。一旦我尝试创建我的数组,我就会得到 "Additional information: Common Language Runtime detected an invalid program.".. 真的不知道如何从这里调试并且 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);
    }

我在这里错过了什么?

你应该初始化局部变量:

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[]));

    ....
    ....