引用全局程序集缓存

Referencing the Global Assembly Cache

提问人:Kevin 提问时间:10/19/2011 最后编辑:CommunityKevin 更新时间:6/19/2015 访问量:5289

问:

我有一个项目需要使用 NHibernate 与我的 Oracle 数据库进行通信。

我工作场所的许多项目都使用 NHibernate,因此 NHibernate 程序集被放置在全局程序集缓存中,这是一个我不完全理解的工具。根据我的研究,我收集了以下内容:

  1. 全局程序集缓存是许多项目引用的 dll 的中央存储库。这避免了 DLL Hell 的问题 - 当发布 dll 的新版本时,您在缓存中更新它一次,并且引用它的所有 .NET 项目现在都将使用新版本。
  2. 不能在程序集缓存中添加对程序集的引用。“已在 GAC 中注册的程序集将不会出现在 [添加引用] 列表中”。但是,您可以通过破坏注册表来强制显示它们。
  3. 您可以轻松地在程序集缓存中添加对程序集的引用。“只需使用〖添加引用〗窗口即可添加对已安装在 GAC 中的程序集的引用”。(我倾向于不相信这一点,因为我在“添加引用”窗口中看不到任何 GAC 程序集)。
  4. 我工作场所的几个项目确实引用了 GAC 中的许多程序集。这些程序集从未出现在“添加引用”菜单中,因此我知道我的前辈没有使用注册表管理技术。然而,它们显然源自 GAC - 它们的文件路径是 C:\Windows\assembly 的子目录。

第二点显然与其他三点相矛盾,但如果它只是假的,我在引用库时不会有任何问题。它肯定反映了现实,因为我的 GAC 程序集在“添加引用”窗口中无处可寻。

我想知道两件事:

  • 开发人员何时会想要使用 GAC?一个有什么好处 没有注册表诡计就无法引用的库?
  • 我的前任采取了哪些步骤来引用 GAC,不接触注册局?
.NET visual-studio-2008 全局程序集缓存

评论


答:

3赞 Steve Rowbotham 10/19/2011 #1

在项目中添加 GAC 引用的“蛮力”方法是直接编辑项目文件。卸载项目并在与项目中其他引用相同的元素下添加一个,例如:ReferenceItemGroup

<Reference Include="System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
</Reference>

您需要注意,“添加引用”对话框的“.NET”选项卡中程序集的设计时位置与 GAC 中这些程序集引用的运行时分辨率之间存在差异。通过 .NET 选项卡添加引用和文件浏览选项卡的区别在于,在前一种情况下,引用未标记为“复制本地”,因此在运行时将从 GAC 中查找。Microsoft 通常会将要从 GAC 引用的程序集的副本放在 %programfiles%\Reference Assemblies 目录下的文件夹中,但这些程序集仅在设计时使用。

1赞 ℍ ℍ 10/19/2011 #2

1 ....在缓存中更新它一次,引用它的所有 .NET 项目现在都将使用新版本。

不完全是。您可以控制应用是使用新版本还是旧版本。有趣的是,两者可以同时在 GAC 中。

  • 我的前任在不接触注册局的情况下采取了哪些步骤来引用 GAC 中的库?

只需 a) 注册它和 b) 添加引用,浏览到原始 dll 位置。c) 验证新引用是否具有 CopyLocal=false 和 StrongName=trueGacUtil /i

5赞 Hans Passant 10/19/2011 #3

引用它的所有 .NET 项目现在都将使用新版本。

不,这就是所谓的DLL地狱。应用程序引用程序集的特定版本。您可以更新 DLL 并更新使用它的应用程序。并且不会破坏也使用该 DLL 但未重新编译的旧应用程序。您可以使用 GAC 执行此操作,因为它可以存储 DLL 的多个版本。或者,您可以通过将 DLL 与应用程序的 EXE 保存在同一个目录中来轻松执行此操作。

GAC 中的程序集不会显示在“添加引用”对话框中。必然如此,您不知道您的用户在她的 GAC 中存储了什么。请改用开发计算机上的“浏览”选项卡,以确保使用特定版本的 DLL。

GAC 对于需要分发安全更新的公司非常重要。像Microsoft一样。它确保没有未修补的 DLL 副本漂浮在周围。对于解决 COM 的 DLL Hell 问题的 [ComVisible] 程序集也很重要。仅此而已。

评论

0赞 Kevin 10/19/2011
让我问一个后续问题,看看我是否理解你的解释。假设我的项目引用 C:/Kevin/NHibernate.dll。如果我的用户没有该目录,但她的 GAC 中有 NHibernate.dll,她是否能够运行我的项目?同样,如果我的同事下载了我的代码库,他是否需要更改对 C:/Steve/NHibernate.dll 的引用才能构建,或者他的 GAC 中是否有 DLL 就足够了?
0赞 Hans Passant 10/19/2011
如果是正确的版本,是的。如果你不确保部署它,这是一个幸福的事故,几率很低。当您将其与应用的 exe 存储在同一个目录中时,这不是问题。程序集引用的 Copy Local 属性会自动执行此操作。不,如果没有已知目录中的引用程序集,就无法构建。只要发布者不处理它(他们不处理),您的解决方案或项目目录就是一个非常好的地方。
1赞 Kevin 10/21/2011 #4

这似乎是我的前任在 GAC 中添加对程序集的引用的方式:

  1. 打开一个已包含对 GAC 中程序集的引用的项目。
  2. 选择引用并打开“属性”窗格。
  3. 复制引用的完整路径。
  4. 在目标项目中,选择“添加引用”,然后选择“浏览”选项卡。
  5. 将完整路径粘贴到“文件名”文本框中,然后选择“确定”。

但是,看看其他答案,我怀疑这是一个好主意。碰巧的是,开发、测试和生产环境的 GAC 都是相同的。如果未同步 GAC,则引用可能无法保持有效。

0赞 Vinod Srivastav 6/19/2015 #5

可能现在回答为时已晚,但我找到了一种非常简单的方法来做到这一点(无需黑客攻击)。

  1. 将您的 dll 放入 GAC 中
  2. GoTo 项目 --> 属性
  3. 单击“引用路径”,设置 GAC 的路径
  4. 和构建

希望对您有所帮助