-1

我想将运行时方法绑定到类方法(如果我调用运行时方法,它必须调用我的类方法,带或不带参数和返回值)。

如果我没有在调用方法和回调方法上设置参数,我的代码可以工作,但是,如果我设置参数,我会收到错误:“给出错误参数计数不匹配。”:我该如何解决?

    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();
    }
}
4

1 回答 1

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();

或者,更好的是,将我的上面替换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);    

最后你也可以调整回调;)

public void Callback(string ali)
{
    Console.WriteLine(ali); // let me see "aaaaa"
}
于 2016-08-06T22:23:42.693 回答