使用.dll文件比将.cs文件链接到项目的优势(对于我自己的通用帮助程序类/扩展方法)


38

我有一个帮助程序项目,可在我创建的所有应用程序中使用。它包含一些扩展方法和一堆通用帮助程序类,控件等。我会不时更新/扩展帮助程序项目。这些通常是小型且无关的项目,而我是唯一从事这些项目的人。

我尝试了两种使用方法

  • 将.cs文件直接添加(添加为链接)到使用它们的每个项目中
  • 将其编译为.dll并将其添加为参考

我看到了这些方法的一些优点和缺点。
第一个:

  • 更简单,因为帮助程序类被编译到exe文件中,所以我经常可以很容易地提供一个可以正常工作的.exe文件。因为我添加为链接,所以我可以肯定的是,每当构建使用该帮助程序的任何项目时,该帮助程序文件都是最新版本。
  • 甚至更简单,因为我可以分开文件,因此可以在.NET 4.0上良好运行的扩展方法与需要.NET 4.5的扩展方法分开引用,这意味着整个应用程序都可以在.NET 4.0上运行
  • 允许通过代码进行调试,并具有断点等的所有优点。
  • 似乎不是“最佳实践”

第二个:

  • 似乎是正确的方法,但是:
  • 需要我提供一个单独的.dll文件,由于某种原因,该文件对用户来说要困难得多(他们倾向于在没有.dll的情况下共享我的程序,然后该文件在启动时崩溃)
  • 当它被编译成一个.dll时,它将需要.NET的最高版本-我的许多用户都没有.NET 4.5,并且只有我的helper类的某些元素需要这样做,这意味着我可以强迫某些人无故更新他们的系统
  • 我还需要确保每当我更新任何程序时,我都还提供.dll文件-即使我不知道自上一个版本以来是否已对其进行过更改(可能已经更改了,但是它最好是同一版本)。在不跟踪程序集版本的情况下,我看不到一种简单的确定方法,这是额外的工作。现在,当我更新程序时,我只提供更新的exe,并且我希望使其保持小巧和低调。

那么,在这里使用.dll文件的实际好处是什么?请注意,我是唯一编辑所有应用程序和帮助文件的代码的人。


另外,需要澄清的是-应用程序通常很少,而helper类中包含的代码对所有应用程序都是完全通用的(一些简单的字符串比较,路径或XML操作等)


实际上,有人让我意识到刚才还有第三种选择。由于我在separte项目中具有帮助程序代码,因此可以将该项目添加到我每个单独应用程序的解决方案中-该工作方式类似于针对单个文件的“添加为链接”,但我只添加了一个项目...但是正如Doc Brown所注意到的,这实质上意味着无论如何都需要将.dll添加到项目中...

另一种有利于不使用dll文件的事情是能够主动地通过helper类进行调试...


3
您是对的,我什至正在这样做,因为它在.NET要求较高的情况下会有所帮助...但是我不喜欢这样做... 40kb应用程序的安装程序有点过头了:)
Bartosz

3
好吧,您可以始终使用Costura之类的工具,它是用于合并DLL的工具。您可以将所有依赖项合并到EXE,保留单个文件并允许您使用任何必要的库。为了简单起见,这可以自动进行构建过程。
Kroltan 2015年

2
将项目添加到解决方案时,仍然必须部署该项目的DLL,但上面列出了所有缺点。
布朗

2
@DocBrown-天哪,您是对的:)
Bartosz

1
链接.cs文件或项目可能会有另一个缺点。如果您在许多项目中使用这些共享文件,而一个项目需要对共享库进行重大更改,则现在需要重构其他项目。如果没有理由让您的代码不需要更新的逻辑,则引用dll可以使您与之隔离。当共享项目涉及自定义身份验证之类的问题时,我曾参与过此问题的开发团队。客户想尝试对新应用程序进行更改,现在您需要以某种方式对公共库进行版本控制。使用dll可以做到这一点。
Ellesedil's

Answers:


13

您已经发现了大多数优点和缺点。使用cs文件作为引用确实更轻巧,并且通常更易于管理。但是,我建议仅在cs文件完全独立且没有任何特殊构建要求时才使用此方法。

使用单独的DLL

  • 将使对其他实用程序或库的依赖关系明确(只要您没有此类依赖关系,它将很好地工作)

  • 将允许您定义特定的构建配置(例如,如果类仅在x86配置中工作,或者至少需要.NET 4.0,则程序集的构建配置使此要求变得明确)。

因此,尤其是如果您有很多单一类的自包含组件,可以使用对文件的引用,但是如果您有引用其他组件的组件或特定的构建要求,则建议使用DLL。

为了减轻管理许多单独的DLL的问题,您可以创建安装程序包,也可以利用ILMerge,后者可以将一组程序集嵌入到单个可执行文件中。在我们的环境中,我们通过为每个应用程序使用部署脚本来不同地处理问题。该脚本可确保在发布新的应用程序版本时,所有需要的DLL始终交付生产。


好的,非常感谢-因此,我是否正确理解,只要我的助手类没有引用任何其他外部dll(仅包含标准.NET代码),简单地链接它们就不是可恶的事情吗?
Bartosz 2015年

@Bartosz:没有外部DLL,理想情况下,每个帮助程序类都不应使用任何其他帮助程序类,或仅使用存储在同一文件中的其他帮助程序类。老实说,您可以在某种程度上管理助手类A需要将助手类B存储在单独文件中的情况,但是这种方法的伸缩性不好。
布朗

1
@PeterK。-是的,我做到了:)
Bartosz 2015年

1
@whatsisname:不是说这行不通。但是,对我来说,这听起来不像是一种可以简化事情的解决方案,更像是一种可能导致意外问题的解决方案;-)
Doc Brown

1
@Ozkan:在我们的环境中,这只是将xcopy部署到某些网络共享上(有一些额外的步骤来备份以前的版本,并确保当前没有人使用该程序-通过首先重命名部署文件夹来实现)。它知道要部署哪些dll,因为我们将所需DLL的列表硬编码到脚本中-毫无疑问。该解决方案不是完美的,但在大多数情况下适用于我们,除了数十个用户大量使用的程序之外。
布朗

11

当应用程序很大并且有需要更新的部分,而不是整个应用程序时,DLL很方便。因此,如果您正在编写MS Word,则可以方便地将DLL中的拼写检查代码更新,而不必更新整个MS Word。如果您正在编写的是小型实用程序应用程序(或一系列恰好都使用相同代码的自包含应用程序),则无论代码是否嵌入到应用程序中都没有太大区别。


2

您已经在问题中总结了很多,我只需要补充几点。

Mono Options是很好地使用第一种方法的NuGet软件包的一个很好的例子。

另外,如果您决定使用dll,则可以使用Costura之类的工具将该引用作为嵌入式资源嵌入到您的可执行文件中。要使用它,只需添加Costura.Fody软件包:

Install-Package Costura.Fody

实际上,还有一件事-通过将嵌入式项目或文件添加为链接,您还可以通过帮助程序文件一直调试所有代码...
Bartosz 2015年

1
@Bartosz我认为只要您具有正确的pdb文件,您仍然可以在没有“帮助文件”的情况下进行“全部调试”。
扎克2015年

我尝试过Costura的东西,我真的很喜欢!
Bartosz

2

dll是否更有用取决于几个因素:

  1. 代码的大小(编译时)。
  2. 有多少exe使用它。
  3. 您打算多久更新一次代码。
  4. 这些EXE文件是否打算放置在一起或完全分开存在。

共享库的目的是获取多个可执行文件共有的代码并将其集中化,以便所有可执行文件共享一个副本。这样做是为了节省空间并使代码更易于更新。

如果您的帮助器类中的代码量很小,则可能不值得将其移至dll,因为dll中代码的开销可能抵消集中化代码所节省的空间。

此外,如果您仅制作几个可执行文件,则每个可执行文件中的代码大小可能足够小,不会造成问题。但是,使用相同代码的可执行文件越多,将代码移入dll越有益。

举一个简化的例子,假设您的助手类在一个exe文件中编译为128字节,但是当移动到dll时,该dll为512字节。如果只有3个可执行文件,则可以通过在可执行文件中包含代码来节省空间。但是,如果您有5个可执行文件,那么您将拥有一个dll更好,因为5个代码副本(5 * 128 = 640字节)所占用的组合空间大于所占用的空间。通过将代码包含在dll(512字节)中。

现在说,例如,您在助手代码中发现了一个错误。如果使用导入的代码编译了所有可执行文件,则必须重新编译每个可执行文件,然后重新分发重新编译的版本。如果将代码编译为dll,则只需重新编译并重新分发一个dll,该错误就会自动修复为使用该dll的所有可执行文件。

最后,对于要找到dll的程序,它必须知道在哪里寻找该dll。如果将所有可执行文件放在一起,则只需将dll放在同一目录中,他们都将立即找到它。如果您有意将它们分开,则很难协调它们以使用相同的dll。


1

您的第三个选项是最合适的(将其作为单独的“类库”项目添加到解决方案中)。这结合了所有方法的优点:

  • 您的“帮助项目”在所有不同的项目上始终是最新的。
  • 要快速查看更改,您可以引用项目的代码。
  • 您可以每次为正确的.NET版本构建它。
  • 您仍然可以将DLL嵌入到exe文件中,因此不必担心您可以将其作为构建的一部分。

我们一直在这样做,除了推荐这种方法我什么也做不了。

您没有提到的另一个第四种选择是将其放在私有的NuGet存储库中,该存储库可让您正确地对其进行版本控制,并在每个解决方案中无需额外项目的情况下对其进行引用。


2
嗯,在我看来,当我将其作为一个项目添加到解决方案中,然后在其他项目中引用该项目时,它仍然是作为单独的.dll创建的,而不是被嵌入的……我应该指定什么吗?
Bartosz 2015年

1

作为开发人员,我总是喜欢将实用程序的解决方案引用包括到我的应用程序中,因为它允许我调试代码(并发现实用程序中可能存在的错误!),并且对该实用程序所做的任何更改都会自动包含在应用程序中。

因此,实际决定取决于实用程序的成熟程度!如果不确定Utility的错误,则应始终包括该实用程序的.cs文件以查找错误。.但是,如果您确定Utility足够成熟并且不会返回包含任何bug的结果,没有在实用程序中进行增强的范围,您可以继续并包含DLL文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.