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时,您可以使用字段、实例和方法复制整个类。如果你不想要这个,你最好用表达式。