在C#项目中引用exe文件是不好的做法

Gig*_*ice 28 .net c#

我有一个简单的问题.

我知道我可以在我的C#项目中引用.net可执行文件.

我不想用"输出类型:Windows应用程序"进行不必要的项目来调用一些dll.

我只是想知道它是否可以或者是一个不好的做法来引用exe文件?

Iva*_*vov 28

是的,由于以下原因,这可能被视为一种不良做法:

  • 糟糕的项目架构
    如果您需要从.exe调用某些逻辑,那么该逻辑就会被错误地放置在那里.相反,您应该将它放在一个单独的dll中,并从您当前引用的可执行文件和引用该可执行文件的应用程序引用相同的.dll.正如下面的评论中所建议的那样,将逻辑提取到库中可以帮助您避免一些CPU架构限制,我将在下一点中对其进行描述,因为可以构建库来定位任何CPU.

  • 架构限制
    引用可执行文件可能已建成以解决最佳32位或64位的机器,甚至是特定的CPU(如安腾).可以在没有这些规范1的情况下构建库,以便与CPU兼容,因此以后可以被任何项目引用.如果引用具有特定体系结构设置的可执行文件,则应使用与引用项目的兼容设置.我认为这是一种限制,因为您无法将最终产品分发到某些平台.

  • 使单元测试困难.
    正如Abel 在评论中暗示的那样,您的单元测试将进入他们自己的DLL,他们也需要引用可执行文件.如果您不使用该InternalsVisibleTo属性公开某些内部方法/字段,或者使用反射(这是一种缓慢的替代方法)来检查和断言对象的某些非公开可见状态,则可能很难对其进行测试.可能无法使用InternalsVisibleTo属性集构建可执行文件,如果您回退到反射,则可能会遇到.NET安全问题,导致无法反映可执行文件的成员(例如,因为测试套件在更严格的设置中执行).

    您还将遇到上述架构限制,这将导致您的单元测试使用相同的架构.如果您的测试套件在远程计算机上执行,这可能是一个问题,作为自动构建的一部分(例如在TravisCI,Bamboo,TeamCity等中).然后,CI代理必须符合可执行文件和测试套件的CPU体系结构.如果没有合适的代理,则不能运行任何测试.此外,如果您使用公共CI平台来构建应用程序并执行测试,则可以将其视为法律意义上的可执行文件的分发.您可能会违反可执行文件的许可证 - 有关详细信息,请参阅下一节.

  • 潜在的许可问题
    您应该仔细分发您的应用程序.如果引用的可执行文件需要额外的许可证或费用才能使用,则必须强制用户在您的应用程序旁边接受该可执行文件的许可证(并在需要时付费),否则您有可能进行非法分发它与您的软件.这也意味着您有权首先引用可执行文件.

  • 未知后果
    可执行文件将复制到bin文件夹中,并与应用程序一起安装.没有人知道如果有人浏览bin文件夹并执行它会发生什么.有一些问题:

    • 由于输入不当,可执行文件崩溃或行为不当.通常,如果它没有任何GUI,就会发生这种情况(例如,如果用户双击命令行程序,它将不会以命令行参数的形式获得任何输入,从而导致崩溃或行为异常).

    • 可执行文件不打算由程序所有者使用,因为这在合法或逻辑上与软件的作用相矛盾.

然而,在某些情况下,引用可执行文件是合理的,但这些是非常罕见的:

  • 可执行文件来自第三方,并且不存在具有相同功能的库,并且没有其他方法可链接到该功能.它也可能是您的雇主或客户建立的项目的明确要求.
  • 可执行文件是用另一种语言编写的,您需要通过互操作与它通信.

只要后者不适用于您,特别是如果您开发自己引用的可执行文件,我肯定会建议将所需的逻辑提取到单独的库中.


1实际上,您也可以构建一个可执行文件来定位任何CPU,如Dominic Kexel的评论所述.相反的情况也是可能的 - 为特定的CPU构建一个库,但它不常见,因为可执行文件通常是为硬件定制的.因此,为了澄清我的观点,我想到了引用第三方可执行文件,或者因其他原因无法重建的可执行文件,并且该可执行文件已针对某些特定体系结构进行了优化.如果您可以重建和更改可执行文件的目标CPU,那么您绝对可以将所需的逻辑提取到dll中.

  • *可执行文件可以构建为最佳地解决32位或64位架构.可以在没有这些规范的情况下构建库*您也可以使用`AnyCPU`构建一个exectuable.如果你的意思是其他的,你能详细说明如何构建一个可执行文件来解决最佳的32位或64位架构? (2认同)
  • 很好的答案,但我认为你错过了几乎每个项目都遇到的一个非常重要的用例:单元测试.通常,单元测试会进入自己的DLL.为可执行文件创建单元测试的自然方法是链接到该可执行文件,并在单元测试DLL中编写(public/protected/internal-with-internalsVisibleTo)方法,属性等的测试. (2认同)

Kja*_*tan 9

如果你在项目中包含一个可执行文件作为资源,那么我认为如果它解决了你的问题并且有效,那就没什么大不了的了(虽然从理论上讲,将常用逻辑提取到一个.dll可以使用的单独的逻辑似乎更正确在几个项目中).

但是:您可能希望将其.exe作为嵌入式资源包含在内,以便在构建项目时直接在输出目录中看到它:

右键单击项目节点,然后选择Add > Existing Item并查找该.exe文件.现在在解决方案资源管理器中右键单击它,选择properties并设置Build ActionEmbedded Resource.

现在,这将是"烤成"自己的.dll或.exe或任何你正在建设,而不是简单地复制到你的输出目录.

  • +1。我喜欢嵌入式资源的想法。这确实可以解决许多潜在的部署问题和不必要的用户操作(如果用户运行该可执行文件)。价格将是获取可执行文件逻辑的样板代码-而不是像使用dll那样进行引用,因此将需要一些反射材料以及临时目录空间以提取exe。 (2认同)