【问题标题】:Referencing different versions of the same assembly引用同一程序集的不同版本
【发布时间】:2010-09-18 09:38:22
【问题描述】:

如果 A 引用程序集 B 1.1 和 C,而 C 引用 B 1.2,如何避免程序集冲突?

我曾假设 C 的引用会被封装掉,不会引起任何问题,但似乎所有 dll 都被复制到了 bin 中,这就是问题发生的地方。

我了解解决此问题的两种方法是使用 GAC 或程序集绑定? GAC 对我来说似乎不是最好的方法,因为我不喜欢假设 dll 会在那里,我更喜欢在我的解决方案中从 lib 目录中引用 dll。

在我看来,程序集绑定并不可靠,如果程序集的一个版本具有另一个版本没有的功能,这不会产生问题吗?


在我的情况下,这是因为我使用的是 3rd 方 dll,使用的是旧版本的 nHibernate,而不是我自己使用的。

【问题讨论】:

  • 我认为您的标题中有错字。 “相同的不同”应该只是“不同的”。 :)

标签: c# dll build-process assemblies versioning


【解决方案1】:

我过去使用 GAC 也取得了相同的结果,但您应该质疑您必须参考多个版本的原因,并尽可能避免使用它。如果您必须这样做,binding redirect 可能会对您的情况有所帮助。

另外,你读过this了吗?

【讨论】:

    【解决方案2】:

    一种看似鲜为人知的方法是使用 extern 关键字。

    来自C# Reference

    要引用具有相同完全限定类型名称的两个程序集, 必须在命令提示符下指定别名,如下所示:

    /r:GridV1=grid.dll

    /r:GridV2=grid20.dll

    这将创建外部别名 GridV1 和 GridV2。要使用这些 程序中的别名,使用 extern 引用它们 关键词。例如:

    外部别名 GridV1;

    外部别名 GridV2;

    每个外部别名声明都会引入一个额外的根级别 与全局平行(但不在其中)的命名空间 命名空间。因此,每个程序集的类型都可以在没有的情况下被引用 通过使用其完全限定名称来消除歧义,该名称植根于 适当的命名空间别名。

    在前面的示例中,GridV1::Grid 将是来自 grid.dll,而 GridV2::Grid 将是来自 grid20.dll 的网格控件。

    【讨论】:

    • 那么,您如何实际使用它?这是什么命令提示符,如何将其集成到构建过程中?
    • 这很好用,只是提供者通常不会在版本之间更改 dll 的名称,因此您最终会尝试引用两个具有相同名称的程序集。 Studio 不喜欢这样,并且不确定地将其中一个复制到输出文件夹,因此这仅在 dll 按版本具有不同名称时才有效。
    【解决方案3】:

    我被要求支持多个版本的程序集并找到了这个解决方案:

      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="MyAssembly" publicKeyToken="..." />
            <codeBase version="1.1.0.0" href="MyAssembly_v1.1.0.0.dll"/>
            <codeBase version="2.0.0.0" href="MyAssembly_v2.0.0.0.dll"/>
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    

    【讨论】:

    • 仅供参考,添加到app.Config ,希望有所帮助。
    【解决方案4】:

    您可以将bindingRedirect element 添加到配置文件中,以指定要在运行时使用的程序集版本。

    <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <dependentAssembly>
                <assemblyIdentity name="myAssembly"
                                  publicKeyToken="32ab4ba45e0a69a1"
                                  culture="neutral" />
                <bindingRedirect oldVersion="1.0.0.0"
                                 newVersion="2.0.0.0"/>
             </dependentAssembly>
          </assemblyBinding>
       </runtime>
    </configuration>
    

    【讨论】:

    • 是的,我在问题中提到过,如果程序集中有不同的功能会发生什么?
    【解决方案5】:

    .NET 运行时完全能够同时加载同一程序集的多个版本。但是,如果您要打开这个蠕虫罐头,我强烈建议您只命名您的程序集并使用 Major.Minor.* 命名方案以避免命名冲突。

    我认为您不应该想出一种千篇一律的方法来使用(或不使用)GAC。如果您想自动使用随 DLL 的未来版本发布的新功能,GAC 会非常好。当然,这种祝福的代价是新版本可能不会像您期望的那样工作:)。这完全取决于什么是最实用的,以及您对发布到 GAC 的内容有多少控制权。

    问候, -艾伦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-30
      • 2014-03-09
      • 2010-09-08
      • 1970-01-01
      相关资源
      最近更新 更多