C# 通过Emit通过委托调用静态泛型方法

C# 通过Emit通过委托调用静态泛型方法,c#,generics,reflection,static,reflection.emit,C#,Generics,Reflection,Static,Reflection.emit,我尝试创建一个delegte来调用静态泛型方法。但我得到了错误:检测到无效代码!你知道我的IL有什么问题吗 示例代码中的FindStaticMethod调用正在工作并返回一个方法信息,带有给定的类型参数 public delegate object GenericStaticInvoker(params object[] arguments); public static GenericStaticInvoker GenericMethodInvokerStaticMethod(Type

我尝试创建一个delegte来调用静态泛型方法。但我得到了错误:检测到无效代码!你知道我的IL有什么问题吗

示例代码中的FindStaticMethod调用正在工作并返回一个方法信息,带有给定的类型参数

 public delegate object GenericStaticInvoker(params object[] arguments);

 public static GenericStaticInvoker GenericMethodInvokerStaticMethod(Type type, string methodName, Type[] typeArguments, Type[] parameterTypes)
    {
        MethodInfo methodInfo;
        ParameterInfo[] parameters;

        // find the method to be invoked
        FindStaticMethod(type, methodName, typeArguments, parameterTypes, out methodInfo, out parameters);

        string name = string.Format("__MethodInvoker_{0}_ON_{1}", methodInfo.Name, methodInfo.DeclaringType.Name);

        DynamicMethod dynamicMethod;
        dynamicMethod = new DynamicMethod(name, typeof(object), new Type[] { typeof(object[]) }, methodInfo.DeclaringType);

        ILGenerator generator = dynamicMethod.GetILGenerator();

        // define local vars
        if (methodInfo.ReturnType != typeof(void))
            generator.DeclareLocal(methodInfo.ReturnType);

        for (int i = 0; i < parameters.Length; i++)
        {
            // load paramters they are passed as an object array
            generator.Emit(OpCodes.Ldarg_1);

            // load array element
            generator.Emit(OpCodes.Ldc_I4, i);
            generator.Emit(OpCodes.Ldelem_Ref);

            // cast or unbox parameter as needed
            Type parameterType = parameters[i].ParameterType;
            if (parameterType.IsClass)
            {
                generator.Emit(OpCodes.Castclass, parameterType);
            }
            else
            {
                generator.Emit(OpCodes.Unbox_Any, parameterType);
            }
        }

        // call method
        generator.EmitCall(OpCodes.Call, methodInfo, null);

        // handle method return if needed
        if (methodInfo.ReturnType == typeof(void))
        {
            // return null
            generator.Emit(OpCodes.Ldnull);                
            generator.Emit(OpCodes.Ret);
        }
        else
        {
            // box value if needed
            if (methodInfo.ReturnType.IsValueType)
            {
                generator.Emit(OpCodes.Box, methodInfo.ReturnType);
            }

            // store to the local var
            generator.Emit(OpCodes.Stloc_0);

            // load local and return
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Ret);
        }



        // return delegate
        return (GenericStaticInvoker)dynamicMethod.CreateDelegate(typeof(GenericStaticInvoker));
    }
public委托对象genericstationvoker(params对象[]参数);
公共静态GenericStationVoker GenericMethodInvokerStaticMethod(类型类型、字符串方法名称、类型[]类型参数、类型[]参数类型)
{
方法信息方法信息;
ParameterInfo[]参数;
//查找要调用的方法
FindStaticMethod(类型、方法名称、类型参数、参数类型、out方法信息、out参数);
string name=string.Format(“\uuuuu MethodInvoker\u{0}\u ON\u{1}”,methodInfo.name,methodInfo.DeclaringType.name);
动态方法动态方法;
dynamicMethod=新的dynamicMethod(名称、typeof(对象)、新类型[]{typeof(对象[])}、methodInfo.DeclaringType);
ILGenerator=dynamicMethod.GetILGenerator();
//定义局部变量
if(methodInfo.ReturnType!=typeof(void))
生成器。DeclareLocal(methodInfo.ReturnType);
对于(int i=0;i
  • 在实例方法中,“this”参数可以通过Ldarg_0加载到计算堆栈上,然后“实际”参数可以通过Ldarg_{x}(通过x1到N)加载

  • 当您有一个静态方法(也是任何lambda的情况,无论它是reflection.emitted还是not)时,“实际”参数可以用Ldarg_{x}(x 0到N-1)加载

  • 总结一下一般情况:“this”引用本身就是一个参数。 它的缺失不会在堆栈上留下一个空插槽(ldarg.0将并且必须用于第一个非-this”参数)

因此,在您的特定情况下,您不能使用操作码。Ldarg_1加载您的params对象[]参数唯一参数:

// ...etc...
for (int i = 0; i < parameters.Length; i++)
{
    // load paramters they are passed as an object array
    generator.Emit(OpCodes.Ldarg_1);

    // ...etc...
/…等等。。。
对于(int i=0;i
您应该使用操作码。Ldarg\u 0:

// ...etc...
for (int i = 0; i < parameters.Length; i++)
{
    // load paramters they are passed as an object array
    generator.Emit(OpCodes.Ldarg_0);

    // ...etc...
/…等等。。。
对于(int i=0;i
  • 在实例方法中,“this”参数可以通过Ldarg_0加载到计算堆栈上,然后“实际”参数可以通过Ldarg_{x}(通过x1到N)加载

  • 当您有一个静态方法(也是任何lambda的情况,无论它是reflection.emitted还是not)时,“实际”参数可以用Ldarg_{x}(x 0到N-1)加载

  • 总结一下一般情况:“this”引用本身就是一个参数。 它的缺失不会在堆栈上留下一个空插槽(ldarg.0将并且必须用于第一个非-this”参数)

因此,在您的特定情况下,您不能使用操作码。Ldarg_1加载您的params对象[]参数唯一参数:

// ...etc...
for (int i = 0; i < parameters.Length; i++)
{
    // load paramters they are passed as an object array
    generator.Emit(OpCodes.Ldarg_1);

    // ...etc...
/…等等。。。
对于(int i=0;i
您应该使用操作码。Ldarg\u 0:

// ...etc...
for (int i = 0; i < parameters.Length; i++)
{
    // load paramters they are passed as an object array
    generator.Emit(OpCodes.Ldarg_0);

    // ...etc...
/…等等。。。
对于(int i=0;i
我需要这个精确的代码,你有没有可能用工作解决方案更新你的问题?我需要这个精确的代码,你有没有可能用工作解决方案更新你的问题?