c# - Reflection.Emit 实现接口(interface)并创建数组 IL

标签 c# proxy runtime il emit

我正在尝试从接口(interface)创建代理类。在方法中,我只想收集对象数组中的所有参数并传递给已知方法。到目前为止,我已经设法让它在没有参数和返回类型的情况下工作。当我尝试创建数组时,我收到“其他信息:公共(public)语言运行时检测到无效程序。”.. 真的不知道如何从这里进行调试,并且 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[]));

    ....
    ....

关于c# - Reflection.Emit 实现接口(interface)并创建数组 IL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33598775/

相关文章:

android - 在 1.x 和 2.x Android 设备上为 WIFI 网络设置电话 HTTP 代理

java - Servlet 启动外部进程

java - 从 Java 程序中编译 .java 文件?

c# - 如何按降序对 DateTime 对象的 ArrayList 进行排序?

windows - 如何在docker工具箱中设置代理?

c# - 无法在 VS2012 上安装 HtmlAgilityPack

c++ - (Re)Using std::algorithms with non-standard containers

c++ - 仅特化模板函数实现的一部分

c# - Unity C# 将float转换为字节数组并用node js读取

If语句的C#重构