7

我有一个项目,它有一组二进制依赖项(我没有源代码的程序集 dll)。在运行时,这些依赖项需要预先安装在机器上,而在编译时,它们需要在源代码树中,例如在 lib 文件夹中。由于我也在为这个程序提供源代码,所以我想为它启用一个简单的下载和构建体验。不幸的是,我无法重新分配 dll,这使事情变得复杂,因为 VS 在不访问引用的 dll 的情况下不会链接项目。

无论如何,在没有真正引用的 dll 的情况下,是否可以构建和链接该项目?

也许有一种方法可以告诉 VS 链接到自动生成的 dll 存根,以便它可以在没有原始文件的情况下重建?也许有第三方工具可以做到这一点?在这方面有什么线索或最佳实践吗?

我意识到这个人必须有权访问 dll 才能运行代码,所以他可以将它们添加到构建过程中是有道理的,但我只是想避免他们收集所有 dll 并将它们放在lib 文件夹手动。

4

5 回答 5

2

对于上面所有的好建议,同意。话虽如此,也许存在通常不需要外部 DLL 的有效场景?所以这就是你要做的。你包装和隔离它们。(它比创建接口的抽象级别更高,因此更容易维护)。

在 Visual Studio 中,如果您不重新编译引用外部 DLL 的特定 VS 项目,那么您可以在不使用这些 DLL 的情况下编译其余的 VS 解决方案项目。因此,如果您以某种方式用自己的 DLL 包装外部 DLL,然后仅将这些包装器分发为二进制文件,那么共享您的源代码的人将不需要外部 DLL 来编译主要解决方案。

注意事项: 1. 将包装代码分离成独立项目的额外工作。2. 其他 VS 项目必须添加对包装 DLL 的引用作为对“LIB”文件夹的“文件系统”引用,而不是“项目引用”。3. VS 解决方案配置必须禁用包装 DLL 的编译。如果需要,应添加新配置以显式重新编译它们。4. 每个 Wrapper DLL 的 VS 项目定义应包含一个构建后事件,以将它们复制到预期的“LIB”文件夹位置。5. 在运行时,外部 DLL 必须存在于应用程序的 bin 目录或机器的 GAC 中,或者以其他方式显式加载。注意:如果它们丢失,只有当它们在运行时实际调用时,它们的缺失才会导致运行时错误。IE 如果代码在一般情况下没有碰巧调用它们,则不需要它们。6. 在运行时,您可以捕获加载外部 DLL 的错误并向用户显示一个漂亮的错误消息,说“要使用此功能,请安装以下产品:xyz”。这比显示“AssemblyLoadException... 请使用 FusionLogViewer... 等”更好。 7. 在应用程序启动时,您可以测试和检测丢失的 DLL,然后禁用依赖它们的特定功能。

例如:根据这种模式,我可以有一个与 Microsoft CRM 和 SAP 集成的应用程序,但仅限于特定功能,即导入/导出。
在设计时,如果开发人员从不需要更改包装器,他们将能够在没有这些外部 DLL 的情况下重新编译。在运行时,如果用户从不调用此函数,则应用程序将永远不会调用包装器,因此不需要外部 DLL。

于 2010-03-16T16:14:00.817 回答
2

也许这些想法之一将帮助您解决问题:

  • 从第 3 方 dll 中的所有类派生接口。将这些接口放入自己的项目中(相同的解决方案),并添加对此接口程序集的引用。还将 EventHandler 添加到AppDomain.AssemblyResolve并尝试在运行时查找和加载程序集。(学分归 NG)
    • 根据 dll 的大小以及对公共部分进行更改的频率,这可能会非常痛苦。
  • 提供一个 readme.txt,您可以在其中解释如何获取所需的程序集以及用户应将它们相对于项目路径放在何处。通常 VS 足够聪明,可以在您将程序集放入正确的位置后立即删除感叹号,项目从中引用它(也许您必须在解决方案资源管理器中按刷新)(致谢 Paul)
    • 不要忘记通过右键单击您的解决方案并选择“添加 -> 现有项目”将 readme.txt 也添加到您的解决方案中。在这种情况下,它将在 Visual Studio 解决方案资源管理器中占据相当突出的位置,用户可以通过双击来阅读它。
  • 在您的解决方案中创建另一个项目,该项目能够自动下载所有需要的 dll 并将它们放入正确的位置。也许它应该在开始下载之前预先检查这些所需的文件是否已经存在。设置原始项目的项目依赖项,使其依赖于这个。因此,它将始终在您的原始版本之前构建。然后在原始项目的预构建事件中启动此下载帮助工具,不要忘记使用 int 值退出程序。0 表示成功,任何其他错误,因此 Visual Studio 也知道您的工具是否成功并在挂起丢失的 dll 之前停止编译过程。
    • 也许自动下载文件几乎是不可能的,因为您需要登录网页或使用一些无法通过工具自动下载的 cookie、flash、验证码等。
于 2010-03-16T10:07:39.483 回答
0

我宁愿编译时依赖使我的构建失败,也不愿出现可能需要一些时间来追踪的运行时错误。

在您的解决方案中放置一个 Readme.txt 并明确说明依赖项是什么、从何处获取它们以及如何处理它们。

于 2010-03-16T09:07:33.800 回答
0

好吧,让他们免去收集所有程序集并将它们自己放在 lib 文件夹中的痛苦。然后将它们与存储库中的源代码一起提交。这样,人们从存储库中签出代码也将获得编译项目所需的一切。

于 2010-03-16T08:47:46.430 回答
0

一个相当激烈的可能性是使用分离的接口模式并在运行时以编程方式加载 dll。

于 2010-03-16T08:52:13.830 回答