我有以下C#代码:
public static double f(double x1, double x2 = 1)
{
return x1 * x2;
}
这里是IL代码(ILSpy):
.method public hidebysig static
float64 f (
float64 x1,
[opt] float64 x2
) cil managed
{
.param [2] = float64(1)
// Method begins at RVA 0x20c6
// Code size 4 (0x4)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: mul
IL_0003: ret
} // end of method A::f
如何使用 System.Reflection.Emit 或更好的 Mono.Cecil 来获取它?
答案 0 :(得分:4)
如果我想用Mono.Cecil
做一些事情,我通常会在C#
中使用预期的代码创建一个类/方法。然后我用Mono.Cecil
检查它(确保你在发布模式下运行它)并重新创建它。
因此,您需要MethodDefinition
name
,attributes
和returnType
参数。
名称:“f”
您的方法的属性为:Mono.Cecil.MethodAttributes.FamANDAssem | Mono.Cecil.MethodAttributes.Family | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.HideBySig
返回类型(Mono.Cecil.TypeReference
类型为System.Double
)
至于参数,您可以使用ParameterDefinition
target.Parameters.Add()
您的一个参数有一个默认值,因此其属性必须为Mono.Cecil.ParameterAttributes.Optional | Mono.Cecil.ParameterAttributes.HasDefault
且其Constant
设置为1.0
(在您的情况下)
现在为方法体:
target.Body.GetILProcessor(); // target is your `MethodDefinition` object.
在检查target.Body.Instructions
的说明后,我们会看到以下代码:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: mul
IL_0003: stloc.0
IL_0004: br.s IL_0007
IL_0005: ldloc.0
IL_0007: ret
所以只需按正确的顺序添加代码
processor.Append(OpCodes.Ldarg_0);
之后,将MethodDefinition
注入/保存到相应的程序集中。
我的程序集检查器代码如下所示:
private static void EnumerateAssembly(AssemblyDefinition assembly)
{
foreach (var module in assembly.Modules)
{
foreach (var type in module.GetAllTypes())
{
foreach (var field in type.Fields)
{
Debug.Print(field.ToString());
}
foreach (var method in type.Methods)
{
Debug.Print(method.ToString());
foreach (var instruction in method.Body.Instructions)
{
Debug.Print(instruction.ToString());
}
}
}
}
}