首先定义Emit动态方法时,DynamicMethod和MethodBuilder的DefineParameter方法不是必须的,因为毕竟构造DynamicMethod或MethodBuilder时你需要指定方法的返回值类型和参数类型。然后是ILGenerator可以直接用ld_loc(N)或者sd_loc(N)来操作相应的参数就可以了。至于返回值,直接ret指令就可以。所有如果你没有特殊需要的话,那么DefineParameter方法是不需要调用的。
如果想为参数加入名称,自定义特性,或者其他特殊属性,DefineParameter就派上用场。
先看一个例子,不用DefineParameter,定义一个动态程序集的方法:
//+ using System.Reflection
//+ using System.Reflection.Emit
var mbuilder = tb.DefineMethod("doo",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
CallingConventions.Standard,
null,
new Type[] { typeof(int) });
var ilgen = mbuilder.GetILGenerator();
var loc = ilgen.DeclareLocal(typeof(int));
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stloc_0);
ilgen.Emit(OpCodes.Ret);
在Reflector中可以看到这样的IL:
.method public hidebysig static void doo(int32) cil managed
{
.maxstack 1
.locals init (
[0] int32 num)
L_0000: ldarg.0
L_0001: stloc.0
L_0002: ret
}
参数(int32类型)是没有名称的。
调用DefineParameter,为参数加入名称:
mbuilder.DefineParameter(1, ParameterAttributes.None, "参数1");
注意DefineParameter返回ParameterBuilder类型。如果只是为了定义名称,那么没必要使用这个ParameterBuilder。
用ParameterBuilder可以为参数(或者返回值)加入特性。
代码:
var pbuilder = mbuilder.DefineParameter(1, ParameterAttributes.None, "参数1");
pbuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(System.Runtime.InteropServices.InAttribute).GetConstructor(new Type[0]), new object[0]));
pbuilder.SetCustomAttribute(new CustomAttributeBuilder(typeof(System.Runtime.InteropServices.OutAttribute).GetConstructor(new Type[0]), new object[0]));
Reflector下再看代码: