我有这个方法:
public int Test()
{
ExternalClass cls = new ExternalClass();
return cls.ExternalMethod();
}
我需要使用IL Injection更改它,因此我可以将类型作为参数传递并删除直接对象创建,如下所示:
public int Test(ExternalClass cls)
{
return cls.ExternalMethod();
}
我可以使用<> .Parameters.Add( _ ___ )添加其他参数,并生成新的程序集。
问题是我无法删除新对象创建的指令。以下是我用来删除它的行。
ILProcessor ilProcessor = <<MethodDefinition>>.Body.GetILProcessor();
ilProcessor.Remove(<<newobj instruction>>);
一旦我尝试调用如下所示的修改后的汇编方法,就会抛出错误“Common Language Runtime检测到无效程序。”
ExternalClass ext = new ExternalClass();
int i = prg1.Test(ext);
我知道我可能也需要处理内存分配相关的东西。如果有人能够在这里提供额外的步骤,我将不胜感激。
答案 0 :(得分:6)
您不能只删除newobj
指令;你留下了一个无效的程序,正如运行时告诉你的那样。这里大致是原始方法如何转换为IL:
public Int32 Test()
{
.local ExternalClass 0;
// ExternalClass cls = new ExternalClass();
newobj class ExternalClass();
stloc.0;
// return cls.ExternalMethod();
ldloc.0;
callvirt Int32 class ExternalClass:ExternalMethod();
ret;
}
如果仅删除newobj
指令,则stloc
指令将不会在堆栈中存储任何内容以存储在本地。您需要将方法转换为:
public Int32 Test(ExternalClass cls)
{
// return cls.ExternalMethod();
ldarg.1;
callvirt Int32 class ExternalClass:ExternalMethod();
ret;
}
所以你需要做三件事:
ldloc
指令。ldarg.1
指令。或者,您也可以删除ExternalClass
本地邮件。 (这将由JIT编译器优化,但会使IL图像膨胀。)