反射在评估堆栈上发出推送和附加参数

reflection emit push and additional argument on evaluation stack

我有为函数创建代理的工作代码:

// For this controller, I only want a Get method to server Get request
MethodBuilder myGetMethod =
    tb.DefineMethod("Get",
        MethodAttributes.Public,
        typeof(String), new Type[] { typeof(String) });

// Define parameters
myGetMethod.DefineParameter(
    position: 1, // 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
    attributes: ParameterAttributes.None,
    strParamName: "stringParam"
);

ILGenerator myMethodIL = myGetMethod.GetILGenerator();
Func<string, string> method = (v) => "Poop";
myMethodIL.Emit(OpCodes.Jmp, method.Method);
myMethodIL.Emit(OpCodes.Ret);

我想扩展函数以接受依赖项。例如

Func<string, string, string> method = (v, s) => v + s + "Poop";

myMethodIL.Emit(OpCodes.Ldstr, "Hi");
myMethodIL.Emit(OpCodes.Jmp, method.Method);
myMethodIL.Emit(OpCodes.Ret);

我正在尝试将加载的字符串推送到评估堆栈上,在此之前评估堆栈已经加载了输入参数,因此在调用跳转时参数对齐良好。但是现在我的 func 需要接受一个额外的参数,我需要将加载的字符串压入堆栈。但是,当我 运行 出现此错误时:

Common Language Runtime detected an invalid program.

如何在调用我的代理之前在计算堆栈上弹出一个附加参数?

事实证明,跳转语句仅在转发相同参数时才有效,而不是弄清楚如何编写正确的 IL 我现在只是从 DI 容器中注入我需要的东西。

public static Type CompileResultType(string typeSignature, Dictionary<string, string> propDic)
{
    TypeBuilder tb = GetTypeBuilder(typeSignature);

    tb.SetParent(typeof(DynamicControllerBase));

    ConstructorBuilder ctor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

    foreach (var item in propDic)
    {
        CreateProperty(tb, item.Key, Type.GetType(item.Value));
    }

    // For this controller, I only want a Get method to server Get request
    MethodBuilder myGetMethod =
        tb.DefineMethod("Get",
            MethodAttributes.Public,
            typeof(String), new Type[] { typeof(Test), typeof(String) });

    // Define parameters
    var parameterBuilder = myGetMethod.DefineParameter(
        position: 1, // 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
        attributes: ParameterAttributes.None,
        strParamName: "test"
    );
    var attributeBuilder
        = new CustomAttributeBuilder(typeof(FromServicesAttribute).GetConstructor(Type.EmptyTypes), Type.EmptyTypes);
    parameterBuilder.SetCustomAttribute(attributeBuilder);

    // Define parameters
    myGetMethod.DefineParameter(
        position: 2, // 0 is the return value, 1 is the 1st param, 2 is 2nd, etc.
        attributes: ParameterAttributes.None,
        strParamName: "stringParam"
    );

    // Generate IL for method.
    ILGenerator myMethodIL = myGetMethod.GetILGenerator();
    Func<string, string> method = (v) => "Poop";

    Func<Test, string, string> method1 = (v, s) => v.Name + s;

    myMethodIL.Emit(OpCodes.Jmp, method1.Method);
    myMethodIL.Emit(OpCodes.Ret);

    return tb.CreateType();
}