【问题标题】:Why are referenced DLLs stored with the EXE为什么引用的 DLL 与 EXE 一起存储
【发布时间】:2014-11-06 22:30:57
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# .net dll


    【解决方案1】:

    有没有办法解决这个问题?

    是的 - install the library in the Global Assembly Cache (GAC)。这种方式可供许多应用程序使用。

    阅读How the Runtime Locates Assemblies 以更好地了解引用是如何加载的。允许使用 EXE 部署 DLL 的实际原因是允许“XCOPY 部署”。此外,它还允许来自 NuGet 和其他源的“插入式”库,无需“安装”即可添加。应用程序的附加扩展也更简单,因为它们可以直接复制进来,并且应用程序可以动态加载加载项,而无需注册任何内容。

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

    您还可以阅读Simplifying Deployment and Solving DLL Hell with the .NET Framework,了解有关 .NET 如何使用程序集解决版本控制问题的更多背景信息

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

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

    【讨论】:

    • 添加 nuget 和 packages 规则可能是最佳答案。
    【解决方案2】:

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

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

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

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

    磁盘空间便宜,内存几乎一样便宜。并且为每个程序提供自己的副本可确保新版本 DLL 中的意外更改不会干扰仅使用旧版本测试的程序。

    最后请注意,即使使用 GAC,也可以安装 DLL 的多个版本。所以如果DLL满足必要的要求,就可以显着减少DLL版本问题。

    【讨论】:

      【解决方案3】:

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

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

      第三种选择是在 DLL 项目上执行构建后步骤,将文件复制到所有相关目录。我不会推荐这种方法,因为这将是一场噩梦。

      所有这些都没有考虑到您如何使用/部署您的应用程序以及您必须考虑多少用户/环境。

      【讨论】:

        【解决方案4】:

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

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

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

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

        如果您打算使用第三方插件使您的产品可扩展,那么拥有一个定义应用程序与其插件之间的接口的 DLL 通常会很有帮助。这使插件开发人员更容易知道受支持的 API 中有什么/没有什么。即使您只是使用可扩展性模型来组织由同一公司内的一个大型团队(或一组团队)开发的代码,同样的技术也会很有帮助。

        【讨论】:

          猜你喜欢
          • 2020-08-16
          • 1970-01-01
          • 1970-01-01
          • 2019-03-16
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-03
          相关资源
          最近更新 更多