【问题标题】:Reflection.Emit Implement interface and create array ILReflection.Emit 实现接口并创建数组 IL
【发布时间】:2015-11-08 20:36:55
【问题描述】:

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

}

我尝试 Emit 的方法应该如下所示。

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

我在这里错过了什么?

【问题讨论】:

  • 它是静态的?不需要实例?

标签: c# proxy runtime il emit


【解决方案1】:

你应该初始化本地人:

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

    ....
    ....

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多