我在运行时使用反射发射创建一个对象。我成功创建了字段,属性和获取设置方法。 现在我想添加一个方法。为简单起见,我们假设该方法只返回一个随机数。如何定义方法体?
编辑:
是的,我一直在查看msdn文档以及其他参考文献,我开始对这些东西感到满意。 我看到上面的例子是如何添加和/或多重,但是如果我的方法正在做其他事情该怎么办。我该如何定义“东西” 假设我是动态生成下面的类,我将如何创建GetDetails()方法的主体?
class TestClass
{
public string Name { get; set; }
public int Size { get; set; }
public TestClass()
{
}
public TestClass(string Name, int Size)
{
this.Name = Name;
this.Size = Size;
}
public string GetDetails()
{
string Details = "Name = " + this.Name + ", Size = " + this.Size.ToString();
return Details;
}
}
答案 0 :(得分:20)
您使用MethodBuilder来定义方法。要定义方法体,请调用GetILGenerator()以获取ILGenerator,然后调用Emit方法以发出单独的IL指令。 MethodBuilder的MSDN文档中有一个示例,您可以在Using Reflection Emit页面上找到有关如何使用反射发射的其他示例:
public static void AddMethodDynamically(TypeBuilder myTypeBld,
string mthdName,
Type[] mthdParams,
Type returnType,
string mthdAction)
{
MethodBuilder myMthdBld = myTypeBld.DefineMethod(
mthdName,
MethodAttributes.Public |
MethodAttributes.Static,
returnType,
mthdParams);
ILGenerator ILout = myMthdBld.GetILGenerator();
int numParams = mthdParams.Length;
for (byte x = 0; x < numParams; x++)
{
ILout.Emit(OpCodes.Ldarg_S, x);
}
if (numParams > 1)
{
for (int y = 0; y < (numParams - 1); y++)
{
switch (mthdAction)
{
case "A": ILout.Emit(OpCodes.Add);
break;
case "M": ILout.Emit(OpCodes.Mul);
break;
default: ILout.Emit(OpCodes.Add);
break;
}
}
}
ILout.Emit(OpCodes.Ret);
}
听起来你正在寻找编写MSIL的资源。一个重要的资源是OpCodes类,它有每个IL指令的成员。文档描述了每条指令的工作原理。另一个重要资源是Ildasm或Reflector。这些将让您看到编译代码的IL,这将帮助您了解您想要编写的IL。通过Reflector运行GetDetailsMethod并将语言设置为IL会产生:
.method public hidebysig instance string GetDetails() cil managed
{
.maxstack 4
.locals init (
[0] string Details,
[1] string CS$1$0000,
[2] int32 CS$0$0001)
L_0000: nop
L_0001: ldstr "Name = "
L_0006: ldarg.0
L_0007: call instance string ConsoleApplication1.TestClass::get_Name()
L_000c: ldstr ", Size = "
L_0011: ldarg.0
L_0012: call instance int32 ConsoleApplication1.TestClass::get_Size()
L_0017: stloc.2
L_0018: ldloca.s CS$0$0001
L_001a: call instance string [mscorlib]System.Int32::ToString()
L_001f: call string [mscorlib]System.String::Concat(string, string, string, string)
L_0024: stloc.0
L_0025: ldloc.0
L_0026: stloc.1
L_0027: br.s L_0029
L_0029: ldloc.1
L_002a: ret
}
要动态生成类似的方法,您需要为每条指令调用ILGenerator.Emit:
ilGen.Emit(OpCodes.Nop);
ilGen.Emit(OpCodes.Ldstr, "Name = ");
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Call, nameProperty.GetGetMethod());
// etc..
您可能还想查找MSIL的介绍,例如:Introduction to IL Assembly Language。