Merging DLL's and changing managing namespaces
我想创建一个与第三方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/
Bingo! So by using ILMerge, it becomes
possible to merge the third-party
libraries DLLs in with the Providers
own DLL, meaning we will only have one
DLL to deploy. But that’s not all, we
can actually go one step further, and
tell ILMerge to internalize all
dependencies. What this does it
converts all the third party classes
to be declared as internal, meaning
they can only be used from within the
final DLL. Woo hoo! problem solved =)
鉴于此问题,我的dll的使用者也可能拥有NLog了...当我引用的NLog转变为全部内部时!这正是我想要的。
有人对此有任何反馈或想法吗?
- 是的,这是DLL Hell的全部内容。最坏的一种,自我诱导的那种。无法治愈。
-
@Hans Passant:因此,如果我的组件使用的是nLog版本x,我必须强迫我的客户也将nLog的版本x用于他们的东西,而别无其他?必须有解决办法,对不对?
-
@zespri这是我遇到的类似情况,但是我不想使用GAC,也不想让我的dll用户不得不担心此实现细节...所以这就是为什么我在寻找解决方案并感觉到一定有东西在那里。
-
多数民众赞成在相同的方法,我在下面的编辑答复中建议,但请参阅链接以了解可能的陷阱。
我同意Hans的观点,强烈建议释放并单独注册DLL。
否则,您可能处在DLL地狱中,这会驱使您的消费者离开。
然后您可以设计一些巧妙的部署方法来检测DLL是否已被注册等。
我必须同意@Hans Passant(这是有关经常讨论的DLL地狱的一些信息),但是由于您已经问了这个问题,所以我会尽力回答。
您可以将第三方DLL捆绑为资源。有关详细信息,请参见此问题。
关于您的其他问题,我只是在您自己的名称空间下公开来自第三方DLL的相关类,并可能使用扩展方法来提供所需的任何其他功能。
例如,您可以使用类中的静态方法(例如XyzNLog.Logger.Log())来提供对NLog \\的Log()方法的访问权限,该方法要进行初始化以及代码内部的其他任何内容(静态构造函数或其他内容)否则你会幻想)。
由于您是使用上述方法加载NLog程序集的,因此,您将是唯一可以直接访问嵌入式NLog程序集的用户,并且用户将无法访问它。现在,您没有从NLog中自动暴露所有类的好处,在这种情况下,仍然必须手动暴露它们。
编辑:另一种方法是尝试将ILMerge与/ internalize标志一起使用,如此处所述。您可能无法完全解决问题,但请查看本文以查看是否可以避免作者描述的陷阱。剧透警报:这不是所有的桃子奶油都可以,但是经过足够的努力,它可能会起作用。
- 在这里的示例中,我没有得到的部分是静态方法Logger必须返回一个类型...如果我在项目中没有对NLog的引用,我将返回什么类型?
-
@ vdh_ant,Logger类是包装NLogs Logger的类,您可以使用我引用的链接通过反射获得该类。换句话说,您公开自己的类而不是NLogs。您始终也可以公开接口(ILogProvider),但是在任何一种情况下,您都无法对NLogs类进行编译时访问,并且唯一的运行时访问将是通过反射或类似操作。
-
嗯,所以如果Im包装的类dll具有更复杂的API,则它会更难:(
-
"您可以将第三方DLL捆绑为资源"。如果您正在编写exe,则效果很好,但是如果您正在编写供其他人使用的dll,则效果不佳。通常,通过订阅AssemblyResolve事件,dll不能与AppDomain混为一谈。这可能会导致使用dll的exe作者感到讨厌。
-
@vdh_ant:您正在使用的这个库,它是否以源代码的形式出现?您可以自己重新编译吗?
-
Ya Im只是编写一个dll,因此使使用上述方法变得困难。另外,我可能可以访问源(这使一切变得容易,因为我只需更改源中的名称空间即可),但是如果没有,该怎么办?
-
@zespri,在DLL中处理AssemblyResolve事件会引起什么关注?
-
@vdh_ant,您可以看一下使用Cecil库在运行时提取信息,但是问题仍然存在-您不能干净地公开方法,而不是使用某种Invoke(method)签名语义,返回dynamic对象,对于图书馆的最终用户来说,这听起来像一场噩梦。您问了这个问题,所以我试图回答,但老实说,这种方法本身似乎还不够干净。
-
@vdh_ant,我偶然发现了另一种方法,您可能想尝试一下。香港专业教育学院将其添加到答案。
-
@dawebber:令人担心的是,库不应引入非明显的副作用。该exe可能出于其应有的目的而使用AssemblyResolve,甚至可能会使用它来解析同一版本。它可能希望以不同的方式加载它。另外,您还必须处理偶数处理程序的运行顺序。当然,您可以放进文档中,即"该库使用AssemblyResolve来加载其依赖项。如果要使用AssemblyResolve,则需要在初始化该库之前执行它。您不应该尝试自己加载这些列出的依赖项"但是他失败了。
-
@Zespri,我同意"非表观副作用"的说法,但是Microsoft在应用程序块(企业库或现在称为的任何库)以及其他几个地方使用了它。我看了看这个链接,尽管它们确实展示了使用AssemblyResolve的一些最佳实践,但似乎没有一个表明您有同样的担忧。但是,IMO可能会带来副作用,您的担心是正确的。它更多地涉及在多个线程上讨论的静态链接第三方代码的整个概念,但这就是OT。
-
@dawebber:我只是搜索了Enterprise Library 5.0的源代码,而AssemblyResolve只是支持Visual Studio设计器的组件中的唯一位置。 (Microsoft.Practices.EnterpriseLibrary.Configuration.DesignT ime.dll)我认为,除了VS之外,其他任何exe文件都不会引用它,并且因为exe和dll都来自同一制造商,所以很好。
-
@dawebber:您给IMO的链接讨论的是略有不同的事情。它可以在"部署.NET Framework和应用程序"一章中找到,尽管可以解释,但我认为部署应用程序与库的注意事项存在显着差异。 AppDomain是" global "。可执行文件是控制它的对象,而不是某些库。顺便说一句,我们可以提出一个SO问题,询问社区意见=)
-
@zespri-这正成为一个有趣的讨论,我认为,如果我们参与社区活动,我将学习新的东西。我担心的是,我们作为一组评论的讨论开始削弱OP的问题。因此,我正在寻找新的SO线程!
-
@zespri-结合Microsoft在其中的更多位置:Prism和WPF / Silverlight运行时(这是指向Connect错误的间接链接)