修改现有的.NET程序集

16
有没有一种方法可以修改现有的.NET程序集而不必使用第三方工具?我知道PostSharp可以做到这一点,但我认为PostSharp的开发者基本上不得不重写整个System.Reflection命名空间的功能才能使现有的程序集可修改,这非常浪费。 System.Reflection.Emit只允许创建新的动态程序集。然而,所有在此处使用的构建器类都继承自基本反射类(例如,TypeBuilder继承自System.Type)。不幸的是,似乎没有办法强制将现有的动态加载类型转换为类型构建器。至少,没有官方支持的方法。
那么不受支持的方式呢?有人知道是否存在后门,允许将现有的程序集或类型加载到这样的构建器类中吗?
注意,我不是在寻找修改当前程序集的方法(这甚至可能是一个不合理的请求),而只是想修改从磁盘加载的现有程序集。我担心没有这样的东西,但我还是想问问。
在最坏的情况下,人们将不得不使用ildasm.exe来反汇编代码,然后使用ilasm.exe进行重新汇编,但.NET中没有包含工作于IL数据的工具链(即IL读取器)。(或者有吗?)
/编辑:

我没有特定的使用案例,只是对通用解决方案感兴趣,因为修补现有程序集是一项非常常见的任务。以混淆器、分析器或AOP库为例(是的,后者可以以不同的方式实现)。正如我所说,被迫重写已经存在于System.Reflection中的大部分基础设施似乎非常浪费。


@Wedge:

你说得对。然而,这里没有具体的用例。我修改了原始问题以反映这一点。我的兴趣是被另一个问题引发的,该提问者想知道如何在每个方法的末尾注入指令popret,以防止Lutz Roeder的Reflector重新设计(VB或C#)源代码。

现在,可以使用许多工具实现此场景,例如上面提到的PostSharp和Reflector的Reflexil插件,后者又使用Cecil库。

总之,我对.NET框架并不满意。

@Joel:

是的,我知道这个限制。无论如何感谢您指出这一点,因为这很重要。

@marxidad:

这似乎是唯一可行的方法。但是,这意味着您仍然必须使用构建器类重新创建完整的程序集,对吗?也就是说,您必须手动遍历整个程序集。

嗯,我会研究一下。

6个回答

11

Mono.Cecil还允许您从给定的程序集中移除强名称,并将其保存为未签名的程序集。一旦从程序集中移除了强名称,您就可以修改目标方法的IL并像使用任何其他程序集一样使用该程序集。这是使用Cecil移除强名称的链接:

http://groups.google.com/group/mono-cecil/browse_thread/thread/3cc4ac0038c99380/b8ee62b03b56715d?lnk=gst&q=strong+named#b8ee62b03b56715d

一旦您删除了强名称,就可以对该程序集进行几乎任何操作。祝使用愉快!


10

您可以使用 MethodInfo.GetMethodBody().GetILAsByteArray() 方法获取方法体的字节数组,进行修改后,再将其插入到 MethodBuilder.CreateMethodBody() 中。


2
你有例子吗?我找不到能让我在现有程序集或类型上创建方法生成器的例子,只有创建新程序集或类型的。 - Preet Sangha
2
这仅用于创建新的。但是,您可能能够在单独的AppDomain中从磁盘加载程序集,然后卸载AppDomain并将新程序集保存在旧程序集上。 - Mark Cidade

4

如果您能提供更具体的用例,将有可能有比这更好的解决方法。

在.NET 3.5中,可以向现有框架类添加扩展方法,也许这已经足够了?


3

一个重要的点:如果该程序集已经签名,任何更改都将失败,你最终将得到一个无用的程序。


1

.NET Framework的程序集是经过签名的,正如Joel Coehoorn所说,你会得到一个无用的东西。


-3
你可以使用 IronRuby 加载程序集,并混入你想要的所有功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接