1

我有这个方法:

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>>);

一旦我尝试调用修改后的汇编方法,如下所示,它会抛出错误“公共语言运行时检测到无效程序”。

ExternalClass ext = new ExternalClass();
int i = prg1.Test(ext);

我知道我可能也需要处理与内存分配相关的事情。如果有人能够提供要在此处实施的其他步骤,我将不胜感激。

4

1 回答 1

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;
}

所以你需要做三件事:

  1. 将参数添加到方法签名中,
  2. 删除包括ldloc指令在内的所有内容。
  3. ldarg.1在方法的开头插入一条指令。

或者,您也可以删除ExternalClass本地。(这将被 JIT 编译器优化掉,但会使 IL 映像膨胀。)

于 2013-01-02T18:55:39.487 回答