我目前使用一个包含大约 100 个项目的大型解决方案。至少有 10 个项目是可执行应用程序。一些库项目是通过 MEF 和反射而不是直接引用作为插件导入的。如果需要的插件自己的依赖没有复制到使用它的可执行项目的输出或插件目录,我们将在运行时得到反射错误。
我们已经尝试或讨论了以下解决方案,但它们似乎都不合适:
- “硬”引用:最初,我们让可执行项目引用他们需要的其他项目,即使它们最终将作为可选插件导入。这很快就失去了团队成员的青睐,他们需要构建排除某些插件并喜欢从一开始就卸载这些项目。这也使得很难使用 Resharper 或其他工具来清理未使用的引用并删除过时的第三方库,而不会意外地清除对所需插件自身依赖项的“未使用”引用。
- 构建后复制(使用预构建“拉”):在很短的一段时间内,一位高级团队成员将所有插件项目设置为将其输出输出自身 xcopy 到已知的“DependencyInjection”文件夹作为构建后事件。需要这些插件的项目将具有预构建事件,将每个所需的插件复制到它们自己的输出目录中。虽然这意味着插件项目“正确地”不知道它们可能在哪里使用,但这引起了两个主要问题。首先,任何时候对插件项目进行更改,他们都必须分别构建(按顺序)插件项目,然后是他们将测试它的可执行项目(以获取要复制的文件)。重建所有会更方便,但太慢了。第二,
- 构建后复制(推送):目前的解决方案从 xcopy 开始,现在主要在插件项目的构建后事件中使用 robocopy 将所需文件直接复制到使用它们的可执行项目的插件文件夹中。这非常有效,因为如果对插件进行更改,可以直接使用调试器运行。此外,CI 构建不会中断,并且为各种构建禁用某些“可选”插件项目的用户不会因缺少引用而出现构建错误。这似乎仍然很老套,并且在所有单独的构建后窗口中维护起来很麻烦,这些窗口很小且无法扩展。当可执行项目从项目重组中移出或重命名时,直到第二天听到隔夜自动化测试的结果后,我们才会发现损坏的引用。
- 带有引用的“虚拟”项目:一个简单的想法涉及为每个不同的可执行构建配置创建空项目,然后返回到硬引用方法。每个都将使用自己的引用来收集插件及其依赖项。他们还将引用实际的可执行文件并将其复制过来。然后,如果想在特定配置中运行特定的可执行文件,您将运行它的虚拟项目。这个似乎特别臃肿,从未尝试过。
- NuGet:在我对 NuGet 的有限熟悉中,这似乎非常适合使用包,但我不知道如何在一个解决方案内部实现该功能。我们已经讨论过拆分解决方案,但团队中的许多成员都强烈反对。是否可以将 NuGet 与来自同一解决方案的包一起使用?
这种情况的最佳做法是什么?是否有比上述任何一种更好的解决方案来管理像这样的反射依赖项的依赖关系,或者是上述最佳选择之一的改进?