为什么引用的DLL与EXE一起存储

本文关键字:EXE 一起 存储 DLL 引用 为什么 | 更新日期: 2023-09-27 18:29:33

我很难理解为什么DLL被复制到带有引用它的exe的文件夹中。据我所知,我应该制作DLL的原因是为了有可重用的代码。因此,如果我创建了一个被25个应用程序引用的DLL(从而利用了"可重用代码"),那么当我需要在DLL中添加更改功能(比如,更新幕后发生的事情)时,我必须打开并重新编译所有25个应用程序,以确保它们获得新功能。

我有一个具体的例子是一个DLL,它负责创建打印的工单表单。工单表单的布局和外观已更改,但所包含的信息均未更改。在这种情况下,我只需要对底层表单创建代码进行一些更改,但不需要对该代码的实现进行更改(使用完全相同的方法和属性)。我不认为我需要重新构建DLL,然后重新构建引用它的每个应用程序,但事实似乎就是这样。如果不重新生成,则应用程序将继续使用旧版本的DLL。

有办法绕过这个吗?我是不是想错了?我应该做点别的吗?我是不是完全误解了这一切?感谢您提供的任何帮助。

为什么引用的DLL与EXE一起存储

有办法绕过这个吗?

是-在全局程序集缓存(GAC)中安装库。许多应用程序都可以使用这种方式。

请阅读运行时如何定位程序集,以更好地了解如何加载引用。允许DLL与EXE一起部署的实际原因是允许"XCOPY部署"。此外,它还允许NuGet和其他来源的"插入式"库,无需"安装"即可添加。应用程序的附加扩展也简单得多,因为它们只需复制即可,而且应用程序可以动态加载加载项,而无需注册任何内容。

这在很大程度上源于COM世界的痛苦,每个DLL都必须注册,如果你有多个版本不兼容,你会发现自己陷入了"DLL地狱"。NET放宽了这些规则,允许版本与可执行文件一起部署,但仍然提供了一种机制(GAC)来允许共享公共程序集。

您还可以阅读使用.NET Framework简化部署和解决DLL地狱,了解有关.NET如何使用程序集解决版本控制问题的更多背景知识

在您的情况下,可能只是将DLL复制到所有新的应用程序,但有一些因素可能会阻止它:

  • 如果程序集已签名
  • 如果应用程序需要特定版本的程序集
  • 等等

DLL有多种用途。其中一个理论目的是允许多个进程共享同一个DLL。事实上,如果你在GAC中安装了一个DLL,这可以允许.NET将DLL实际加载到内存中一次(即,多个进程同时运行,使用相同的DLL,不要像其他DLL那样,每个进程都在内存中获得自己的DLL副本)。

但另一个目的只是为了代码重用。在这种情况下,DLL的主要功能是作为某些给定功能的可重新分发存储库。多个进程可以使用同一个DLL副本并不重要。相反,重要的是多个进程有一种方便的方式来重用DLL中的功能。

还要注意,对DLL的更改可能有益,也可能不有益。当然,人们总是希望更新版本的DLL更好。但对代码的更改总是意味着有机会在代码中添加新的bug。经过给定版本DLL彻底测试的程序在与同一DLL的较新版本一起使用时可能保持可靠,也可能不保持可靠。

DLL的更新版本通常主要用于添加功能。当然,一些错误可能会在这个过程中得到修复,但同样,如果程序已经用旧版本进行了测试,并且目前正在运行,那么新的错误修复可能并不重要。同时,用旧版本编写的程序可能没有任何实用的方法来利用新功能。

磁盘空间很便宜,内存也同样便宜。为每个程序提供自己的副本可以确保DLL的新版本不会发生意外更改,从而干扰只使用旧版本测试的程序。

最后要注意的是,即使使用GAC,也可以安装多个版本的DLL。因此,如果DLL满足必要的要求,就有可能显著减少DLL版本的问题。

听起来您有一个构建自动化问题(或缺乏)。如果您将所有代码都放在一个容器(TFS、GIT等)中,那么就没有理由不能将所有项目添加到一个主构建解决方案中,并以这种方式分发代码。这样,你只需进入并重新编译主解决方案,文件就会被推送到所有的应用程序中。

另一种选择是使用一个通用的bin文件夹,将所有项目输出到该主目录并从那里执行。这只需要重新编译DLL,其他应用程序就会立即接收到。

第三种选择是在DLL项目上进行后构建步骤,将文件复制到所有有问题的目录中。我不建议采用这种方法,因为维持这种方法将是一场噩梦。

所有这些都没有考虑如何使用/部署应用程序,以及需要考虑的用户/环境数量。

使用DLL的一个较少讨论的优点是,它们可以帮助您构建代码。

将产品拆分为DLL使每个组件的开发人员能够更好地控制可访问性,因为您现在可以使用公共、私有和内部作用域。例如,您可以在一个DLL中拥有一组紧密耦合的类,而不会让其他DLL中的代码滥用允许这种紧密耦合的接口。

将产品拆分为DLL也会迫使您在创建组件之间的依赖关系时考虑构建顺序。

当然,你可以试着在维护高级设计中的层时保持勤奋和自律,但没有什么比构建中断更能让你知道什么时候你添加了不应该存在的依赖项了。当然,也有一些方法可以解决这个问题,但将项目拆分为DLL并按顺序构建它们会迫使您非常明确地添加不遵循简单分层模型的依赖项。

如果你计划让你的产品可以用第三方插件进行扩展,那么有一个单独的DLL来定义应用程序和插件之间的接口通常会很有帮助。这使得插件开发人员更容易知道支持的API中有哪些内容。即使您只是使用可扩展性模型来组织同一公司内的大型团队(或一组团队)开发的代码,同样的技术也会有所帮助。