合并DLL并更改命名空间管理

7
我想创建一个与第三方dll合并的单个dll,这意味着最终用户只需要处理1个dll而不是2个。
为了增加可读性,让我们假设第三方dll是nLog。如果合并后的dll的使用者已经在他们的项目中引用了NLog,那么该怎么办?
理想情况下,我想能够在我的项目中更改NLog名称空间为“XyzNLog”,这意味着用户不需要进行任何别名设置... 你有任何想法如何做到这一点吗?
现在我知道我可以为NLog添加别名,以便我必须将其称为XyzNLog,但我希望相同的别名设置也适用于合并dll的消费者,以便永远不会出现冲突。
更新-解决方案

http://blog.mattbrailsford.com/2010/12/10/avoiding-dependency-conflicts-using-ilmerge/

使用ILMerge,可以将第三方库的DLL合并到提供程序自己的DLL中,这意味着我们只需要部署一个DLL。但这还不是全部,我们实际上可以进一步告诉ILMerge将所有依赖项内部化。这样做会将所有第三方类转换为声明为internal,这意味着它们只能从最终的DLL中使用。问题解决了!通过这种方式,我DLL的使用者也可以拥有NLog...因为我的引用NLog已经全部变为internal了!这正是我想要的。你们有什么反馈或想法吗?

9
是的,这个问题看起来像是典型的“DLL地狱”,而且是最糟糕的自己招惹上身的那种。对于这种情况,没有什么解决方法。 - Hans Passant
@Hans Passant:所以如果我的组件使用nLog x版本,我必须强制我的客户也使用nLog x版本来处理他们的东西,而不是其他版本?一定有解决方案,对吧? - Andrew Savinykh
@zespri 这跟我的情况很相似,但我不想使用 GAC,也不希望我的 DLL 用户担心这个实现细节...所以我正在寻找解决方案,并且感觉一定有办法。 - vdh_ant
这是我在下面修改后的回复中建议的相同方法,请参考链接以了解可能存在的问题。 - dawebber
2个回答

1

我同意Hans的观点,强烈建议在注册DLL之前先进行发布。

否则,你可能会陷入DLL地狱,这会让你的消费者离开。

然后,你可以设计一些巧妙的部署方法来检测DLL是否已经注册等。


0

我必须同意@Hans Passant的观点(以及这里有一些信息关于经常讨论的DLL地狱),但既然你提出了问题,我会尝试回答。

您可以将第三方DLL捆绑为资源。请参阅此问题以获取详细信息。

至于您的其他问题,我建议只公开来自第三方DLL的相关类,并使用扩展方法提供所需的任何其他功能。

例如,您可以使用类中的静态方法(称为XyzNLog.Logger.Log())提供对NLog的Log()方法的访问权限,并在您的代码中处理初始化和其他内部操作(如静态构造函数或其他所需内容)。由于使用上述方法加载NLog程序集,因此您将是唯一能够直接访问嵌入式NLog程序集的用户,而用户无法访问它。现在,您无法从NLog自动公开所有类,但在这种情况下,仍必须手动公开它们。
编辑:另一种方法是尝试使用ILMerge与/internalize标志(如此处所述)。您可能无法完全解决问题,但请查看本文以了解是否可以避免作者描述的陷阱。剧透警告:这个方法也不是完美无缺,但是如果付出足够的额外努力,可能会起作用。

在你提供的例子中,我不理解的部分是静态方法Logger必须返回一个类型...如果我在项目中没有对NLog的引用,我应该返回什么类型? - vdh_ant
@vdh_ant,Logger类是您封装NLog Logger的类,您可以通过我提供的链接使用反射获取它。换句话说,您公开自己的类而不是NLog的类。您始终可以公开接口(ILogProvider),但无论哪种情况,您都无法在编译时访问NLog的类,唯一的运行时访问方式是通过反射或类似方式。 - dawebber
如果我要封装的类 DLL 具有更复杂的 API,那么这将会更加困难。 - vdh_ant
@vdh_ant:你正在使用的这个库,它是以源代码的形式提供的吗?你有重新编译它的选项吗? - Andrew Savinykh
是的,我只是在编写一个dll,所以使用所描述的方法会变得困难。另外,我可能可以访问源代码(这将使一切变得容易,因为我可以在源代码中更改命名空间),但如果我没有呢? - vdh_ant
显示剩余10条评论

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