合并程序集(ILMerge)中的.NET类型定义

6
我正在使用ILMerge将多个.NET程序集合并,其中包括一些第三方程序集。自从这样做以来,我遇到了几个错误,所有这些错误都可以归结为类型定义与其所定义的程序集相关联。
一个简单的例子是我的App.config中的log4net配置部分定义。它使用type="log4net.Config.Log4NetConfigurationSectionHandler,log4net",但在将log4net程序集合并到我的合并后程序集后,它不会起作用,因为log4net程序集不存在。这不是什么大问题,我只需将程序集名称更改为我的合并后程序集名称就可以了,然后它就可以正常工作了。
稍微复杂一点的例子是二进制序列化类型。我的系统使用二进制序列化来在进程之间发送某些对象。所有可序列化的对象都定义在一个公共程序集中,其他所有项目都引用该程序集。我一直在使用默认的二进制序列化,但当反序列化对象时,它开始失败,并显示无法找到序列化对象所在的合并后程序集的错误。同样,并不是什么大问题,我实现了一个自定义SerializationBinder,它在任何已加载的程序集中查找类型,而不仅仅是给定的程序集。
当序列化类型引用其他可序列化类型时,上一个示例变得更加复杂。我继续遇到越来越多的问题,这些问题变得越来越难以处理。
我想说的重点是,.NET类型系统和ILMerge似乎不太兼容。有没有人有解决这个问题的经验?是否有可能告诉.NET运行时,不关心类型所说的程序集,只需要到任何地方查找它?
注意:请不要回复问我为什么要合并程序集,这不是这个问题的重点。

你尝试过使用DataContractSerializer了吗?NetDataContractSerializer绑定了类型,所以你不能使用它,但是普通的DCS应该可以为你工作。 - user1228
3个回答

4
是的,有一个解决方案:使用模块而不是程序集!
.NET编译器有一个选项(C#和VB的/target:module),可以构建模块而不是程序集。然后可以将多个模块传递给编译器,并用于构建最终的程序集。
当然,这一切都假设您拥有那些第三方程序集的源代码。如果您无法获取它,也许可以从第三方获得一个.netmodule版本的第三方程序集?
如果这行不通,您仍然有最后一个选择。显然,您已经将第三方程序集反编译为IL。从该IL文件中删除程序集信息,然后使用“ilasm /dll”构建一个.netmodule,您现在应该能够像使用任何其他.netmodule一样使用它!
通过使用模块而不是程序集,您不应该再遇到任何基于程序集的问题。
确实,我们通过不再使用ILMerge来解决了您的问题,但这难道不是最好的解决方案吗?
希望对您有所帮助,以下是一些有用的链接:
.netmodule代替程序集
使用.netmodules的ILASM
(我曾经以为我的.netmodules经验永远不会对任何人有用!)

0
几年后,我遇到了同样的问题并找到了解决方案。您可以在AssemblyInfo.cs文件中添加[assembly: log4net.Config.XmlConfigurator(ConfigFile = "logging.config", Watch = true)],这将在合并log4net程序集时起作用。

-2
欢迎来到代码中字符串和(物理位置)字符串的困境...
所有这类工具都有类似的问题,它们最好是聪明的,因为许多运行时特性的开发人员和设计师(例如绑定和序列化)并没有真正设想过它,但他们肯定将ILMerge推广为“聪明”的工具。它是如此聪明,甚至不能修剪类型。
注意版本控制也在这里发挥作用,配置、.* 和星际爱好者,以及来自Redmond的版本独立性也没有帮助。
你肯定会遇到第三方组件的麻烦。相信我,我知道你需要合并,因为一些可怜的少数类型对于大型应用程序来说可能需要很长时间才能启动MS JIT(不,我不想要比以前更慢的NGEN或优化的3.5SP1加载,因为由于System.Core或WPF臃肿而导致)。
在我看来,至少在大规模上,最好的选择是获取一个体面的商业工具,它可以扫描和处理这个问题(即从现有的痛苦和混淆经验中)。从长远来看,如果你没有源代码,你可能会最终仪器化现有的IL代码。

[ 然后有一个 INotifyPropertyChanged 字符串发明,解决了全球变暖问题 - 设计者为卡西欧计算器发明家 ]


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