1

静的ジェネリックメソッドを呼び出すためのデリゲートを作成しようとしています。しかし、エラーが発生しました:無効なコードが検出されました!私のILの何が問題なのか誰にも分かりませんか?

サンプルコードのFindStaticMethod呼び出しは機能しており、指定されたType引数を使用してメソッド情報を返します。

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

1 に答える 1

1
  • インスタンス メソッドでは、「this」パラメータを Ldarg_0 によって評価スタックにロードし、次に「実際の」パラメータを Ldarg_{x} (x 1 ~ N) でロードできます。

  • 静的メソッドがある場合 (reflection.emitted かどうかに関係なく、任意のラムダの場合も同様)、「実際の」パラメータは Ldarg_{x} (x 0 から N-1 まで) でロードできます。

  • 一般的なケースについてまとめると、「this」参照はそれ自体がパラメーターです。その不在はスタックに空のスロットを残しません ( ldarg.0は最初の非「this」パラメーターに使用され、使用されなければなりません)。

したがって、特定のケースでは、 OpCodes.Ldarg_1を使用してparams object[] パラメータの一意のパラメータをロードすることはできません。

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

    // ...etc...

OpCodes.Ldarg_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...
于 2013-02-25T13:07:54.183 に答える