如何使用共享程序集和项目?

时间:2010-01-20 15:34:04

标签: c# .net visual-studio

作为序言,我已经使用C#几个月了,但我对部署和汇编等概念完全不熟悉。我的问题很多而且多种多样,虽然我疯狂地用谷歌搜索并阅读它们无济于事(我目前在我面前有Pro C#2008和.NET 3.5平台)。

我们有这个过程,它由三个组件组成:引擎,过滤器和过程逻辑。我们非常喜欢这个过程,我们希望它能在其他项目中重复使用。所以现在我开始探索超越一个解决方案,一个项目的空间。

这听起来不错吗?一个巨大的解决方案:

  • 流程A,exe
  • 流程B,exe
  • 流程C,exe
  • 过滤器,dll
  • 引擎,dll

引擎是所有进程的共享代码,所以我假设它可以是共享程序集?如果共享程序集与使用它的项目在同一解决方案中,如果它应该在GAC中,它将如何被消耗?我已经阅读了一些关于post build事件的内容。这是否意味着必须在每次构建时重新部署engine.dll?

此外,我们将过滤器与进程分离的原因(只有一个进程使用它)是因为我们可以独立于进程部署过滤器,以便不需要更新进程可执行文件。不管这是不是最好的做法,让我们来看看吧。这可能吗?我已经读过程序集链接到其他程序集的特定版本,所以如果我只更新DLL,它实际上被认为是篡改。如何在不更改EXE的情况下更新DLL?这是出版商政策的用途吗?

顺便说一下,谷歌能够或亚马逊能够拥有这些东西吗?我应该寻找什么?我看到很多关于C#和.NET的书籍,但没有关于部署,构建或测试或与语言本身无关的事情。

6 个答案:

答案 0 :(得分:3)

我同意Aequitarum的分析。还有几点:

  

引擎是所有进程的共享代码,所以我假设它可以是共享程序集?

这似乎很合理。

  

如果共享程序集与使用它的项目位于同一解决方案中,如果它应该在GAC中,它将如何被消耗?

万。

好吧,这不是魔术。假设在您的解决方案中,您的流程项目引用了引擎项目。构建解决方案时,您将生成一个项目程序集,它引用了引擎程序集。然后,Visual Studio将各种文件复制到正确的目录中。执行流程程序集时,运行时加载程序知道在当前目录中查找引擎程序集。如果它在那里找不到它,它会在全局程序集缓存中查找。 (这是一个高度简化的加载策略视图;真正的策略比这复杂得多。)

GAC中的内容应该是真正的全局代码;您合理地期望使用大量不同项目的代码。

  

这是否意味着必须在每次构建时重新部署engine.dll?

我不确定“重新部署”是什么意思。就像我说的,如果你有一个项目到项目的引用,构建系统会自动将文件复制到正确的位置。

  

我们将过滤器与进程分离的原因(只有一个进程使用它)是为了使我们可以独立于进程部署过滤器,以便不需要更新进程可执行文件

我怀疑这是否真的有价值。场景一:没有过滤器程序集,所有过滤器代码都在project.exe中。您希望更新过滤器代码;你更新project.exe。场景二:filter.dll,project.exe。您希望更新过滤器代码;你更新filter.dll。情景二如何比情景一更便宜或更容易?在这两种情况下,您都在更新文件;为什么文件的名称是重要的?

然而,对于您的特定场景,也许它确实更便宜,更容易。了解程序集的关键是程序集是可独立版本化和可再发行代码的最小单元。如果你有两件事,并且版本和彼此独立发货是有意义的,那么它们应该在不同的组件中;如果这样做没有意义,那么它们应该在同一个组件中。

  

我已经读过程序集链接到其他程序集的特定版本,所以如果我只更新DLL,它实际上被认为是篡改。如何在不更改EXE的情况下更新DLL?这是出版商政策的用途吗?

组件可以被赋予“强名称”。当您将程序集命名为Foo.DLL,并且将Bar.EXE写为“Bar.EXE依赖于Foo.DLL”时,运行时将加载恰好名为Foo.DLL的任何内容;文件名不强。如果恶意黑客将自己的Foo.DLL版本添加到客户端计算机上,则加载程序将加载它。一个强大的名字让Bar.EXE说“由Bar Corporation编写的Bar.exe版本1.2依赖于Foo公司编写的Foo.DLL版本1.4”,所有的验证都是针对与Foo Corp和Bar Corp.相关的加密密钥完成的。

所以是的,可以将程序集配置为仅绑定特定公司的特定版本,以防止篡改。你可以做些什么来更新程序集以使用更新的版本是创建一个小的XML文件,告诉加载器“你知道我怎么说我想要Foo.DLL v1.4?好吧,实际上如果1.5可用,它可以使用那也是。“

  

我应该寻找什么?我看到很多关于C#和.NET的书籍,但没有关于部署,构建或测试或与语言本身无关的事情。

我同意,书中的部署经常被忽略。

如果您对部署托管Windows应用程序感兴趣,我会先搜索“ClickOnce”。

答案 1 :(得分:1)

项目可以引用程序集或项目。

当您引用另一个程序集/项目时,您可以使用引用程序集中的所有公共类/枚举/结构等。

您无需在一个解决方案中拥有所有这些内容。您可以有三个解决方案,每个流程一个,所有三个解决方案都可以加载引擎和过滤器。

此外,您可以让Process B和Process C引用Engine和Filter的已编译程序集(.dll)并具有类似的效果。

只要您没有在程序集的引用中将属性设置为需要特定版本,您就可以自由地更新DLL而不必担心,只要对DLL进行唯一的代码更改。

  

另外,我们的主要原因   将过滤器与过程分开   (只有一个进程使用它)是这样的   我们可以独立部署过滤器   从过程到这个过程   可执行文件不需要更新。   无论这是最佳做法,   让我们滚动吧。这是   可能的?

我实际上更喜欢这种更新方法。每次更新只更改而不是更改所有内容的文件的开销更少。

至于使用GAC,我将不会涉及其他复杂程度。

可以通过签名来完成对组件的防篡改,这是首先使用GAC所必需的,但只要不需要特定版本,您仍应该没问题。

我的建议是阅读一本关于.NET框架的书。这将真正帮助您了解CLR以及您正在做的事情。

Applied Microsoft .NET Framework Programming是一本我非常喜欢阅读的书。

答案 2 :(得分:1)

您提到引擎是共享代码,这就是您将其放在解决方案下的单独项目中的原因。这样做是没有错的,并且没有必要将此DLL添加到GAC。在开发阶段,您只需添加对引擎项目的引用,您就可以从该程序集中调用代码。当您想要部署此应用程序时,您可以使用它部署引擎DLL,或者您可以将引擎DLL添加到GAC(这是另一个蜡球本身)。除非真的有必要,否则我倾向于依赖GAC部署。 .NET的最佳功能之一是能够在一个文件夹中部署运行应用程序所需的一切,而无需将内容复制到系统文件夹(即GAC)。

如果您希望实现类似动态加载DLL和从处理器调用成员方法而无需关心特定版本,可以使用几条路线。最简单的方法是在添加引用时将Specific Version属性设置为False。这将使您可以在以后更改DLL,并且只要您不使用方法签名,它就不应该成为问题。第二个选项是MEF(使用Reflection并将成为.NET 4.0中框架的一部分)。使用MEF的想法是,您可以扫描实现特定功能的DLL的“插件”样式文件夹,然后动态调用它们。这为您提供了一些额外的灵活性,您可以在以后添加新程序集而无需修改引用。

需要注意的另一件事是,Visual Studio中内置了安装和部署项目模板,您可以使用这些模板生成用于部署项目的MSI包。 MSDN有很多与此主题相关的文档,您可以在这里查看:

http://msdn.microsoft.com/en-us/library/ybshs20f%28VS.80%29.aspx

答案 3 :(得分:1)

在构建计算机上使用GAC,这是一个部署细节。当您引用DLL时,Visual Studio会自动将DLL复制到应用程序的构建目录中。这可确保您使用预期版本的DLL运行和调试。

部署时,您可以选择。您可以将DLL与使用它的应用程序一起发送,存储在EXE安装文件夹中。没有什么特别需要,CLR总能找到DLL,你不必担心强名称或版本。只需将新DLL复制到EXE文件夹即可部署错误修复更新。

当您有几个已安装的应用程序依赖于DLL时,部署错误修复更新可能会开始变得尴尬。因为您必须重复复制到DLL,每个应用程序一次。当您更新某些应用程序而不是其他应用程序时,您可能会遇到麻烦。特别是当DLL接口发生重大变化时,需要重新编译应用程序。那是DLL Hell敲门,GAC可以解决这个问题。

答案 4 :(得分:0)

我们在MSDN上发现了some guidance这个问题。我们从两个单独的解决方案开始,没有共享代码,然后将共性抽象为共享程序集。我们在分离共享代码中的更改以仅影响已准备好的项目方面遇到了困难。我们在Open/Close时很糟糕。

我们试过了

  • 为使用它的每个项目分支共享代码并将其包含在解决方案中
  • 在我们进行更改时从共享解决方案复制共享程序集
  • 编译预构建事件以构建共享代码解决方案并复制程序集

一切都是真正的痛苦。我们最终使用了一个包含所有项目的大型解决方案。我们分支每个项目,因为我们希望将功能更接近生产。这也分支了共享代码。它简化了很多事情,随着公共代码的变化,我们可以更好地了解所有项目中的测试失败。

就部署而言,我们的构建脚本设置为构建代码并仅将已更改的文件(包括程序集)复制到我们的环境中。

答案 5 :(得分:0)

默认情况下,项目中有一个硬编码版本号(1.0.0.0)。只要不更改它,就可以将所有Filter构建与Process程序集一起使用(它只知道它应该使用1.0.0.0版本)。然而,这不是最佳解决方案,因为您如何区分各种构建?

另一种选择是使用相同Process的不同版本的Filter。您应该将app.config文件添加到Process项目,并包含bindingRedirect元素(请参阅文档)。每当运行时查找特定版本的过滤器时,它都会“重定向”到配置中指示的版本。不幸的是,这意味着虽然您不必更新Process程序集,但您必须使用新版本更新配置文件。

每当遇到版本控制问题时,您都可以使用Fuslogvw.exe(融合日志查看器)对这些问题进行故障排除。

玩得开心!

乌鲁