C# 反射发射推送和计算堆栈上的附加参数

C# 反射发射推送和计算堆栈上的附加参数,c#,.net-core,reflection.emit,C#,.net Core,Reflection.emit,我有为函数创建代理的工作代码: // 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 paramete

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

// 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);
//对于此控制器,我只需要一个Get方法来处理Get请求
MethodBuilder myGetMethod=
tb.DefineMethod(“获取”,
方法属性。公共,
typeof(String),新类型[]{typeof(String)};
//定义参数
myGetMethod.DefineParameter(
位置:1,//0为返回值,1为第一个参数,2为第二个参数,依此类推。
属性:参数属性。无,
strParamName:“stringParam”
);
ILGenerator myMethodIL=myGetMethod.GetILGenerator();
Func方法=(v)=>“Poop”;
Emit(opcode.Jmp,method.method);
myMethodIL.Emit(操作码.Ret);
我想扩展func以接受依赖项。e、 g

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方法=(v,s)=>v+s+“Poop”;
myMethodIL.Emit(opcode.Ldstr,“Hi”);
Emit(opcode.Jmp,method.method);
myMethodIL.Emit(操作码.Ret);
我试图将加载的字符串推送到计算堆栈上,在此之前,计算堆栈已经加载了输入参数,因此在调用跳转时,参数会很好地对齐。但是现在我的func需要接受一个额外的参数,我需要将加载的字符串推送到堆栈上。但是,当我运行此命令时,会出现一个错误:

公共语言运行库检测到无效程序


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

事实证明,跳转语句只在转发相同的参数时起作用,而不是找出如何编写正确的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();
}
公共静态类型编译器结果类型(字符串类型签名,字典属性)
{
TypeBuilder tb=GetTypeBuilder(typeSignature);
tb.SetParent(typeof(DynamicControllerBase));
ConstructorBuilder ctor=tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
foreach(propDic中的var项目)
{
CreateProperty(tb,item.Key,Type.GetType(item.Value));
}
//对于这个控制器,我只需要一个Get方法来处理Get请求
MethodBuilder myGetMethod=
tb.DefineMethod(“获取”,
方法属性。公共,
typeof(String),新类型[]{typeof(Test),typeof(String)};
//定义参数
var parameterBuilder=myGetMethod.DefineParameter(
位置:1,//0为返回值,1为第一个参数,2为第二个参数,依此类推。
属性:参数属性。无,
strParamName:“测试”
);
var属性生成器
=新的CustomAttributeBuilder(typeof(FromServicesAttribute).GetConstructor(Type.EmptyTypes),Type.EmptyTypes);
parameterBuilder.SetCustomAttribute(attributeBuilder);
//定义参数
myGetMethod.DefineParameter(
位置:2,//0为返回值,1为第一个参数,2为第二个参数,依此类推。
属性:参数属性。无,
strParamName:“stringParam”
);
//为方法生成IL。
ILGenerator myMethodIL=myGetMethod.GetILGenerator();
Func方法=(v)=>“Poop”;
Func method1=(v,s)=>v.Name+s;
Emit(opcode.Jmp,method1.Method);
myMethodIL.Emit(操作码.Ret);
返回tb.CreateType();
}

也许您想调用您的方法?不能跳转到方法,只能跳转到标签。为什么要混合使用表达式和发出操作码?做一个或另一个。你想构建一个完整的类吗?但这只有在类具有实例字段时才有用。但表达式是静态方法,永远无法访问实例字段。因此,如果所有的方法都是静态的,那么就可以使用表达式,如果必须是实例方法,那么就必须用操作码来表达整个逻辑。您也不能将“this”指针传递到表达式,因为在编译时类型未知。@Holger跳跃语句目前有效,我尝试使用call和virt call,但在编译器中没有任何效果。该方法提供了ilbytes。我在示例中使用funcs是因为我使用它来创建动态控制器,并且我想为用户提供一种动态公开他们自己的define方法的方法。所以他们传递了一个funcok,所以我发现关于我的Jmp语句的更多信息只能在参数为的情况下转发,sameA跳转没有参数。跳转是实现循环(“for”、“while”)或“If”的东西。(C#中的“goto”)表达式与ILCode做的事情相同——在运行时创建一些东西,但它的级别更高,所以不容易出错。在某个时刻,您可以调用LambdaExpression.Compile,并获得可运行的ILCode。同样的道理。但是表达式一次只能有一个纸牌独立方法。使用TypeBuilder/MethodBuilder时,您可以使用字段、实例和方法复制整个类。如果你不想要这个,你最好用表达式。