5

我有一个包含 2 个项目的解决方案:Proj1 和 Proj2,其中 Proj1 是启动项目。

Proj1 引用 Proj2(为了调用 Proj2 的类),并且它的现有代码还引用了一个名为 A 的第 3 方 DLL,版本为 1.0.0.0。

Proj2 引用了相同的第 3 方 DLL A,但它在 2.0.0.0 版本中引用它,因为该项目中的类需要更新的实现,而 1.0.0.0 中没有。

到目前为止,我已经尝试了以下操作: 1. 引用 A 时将“特定版本”切换为 true 2. 在 Proj2 中添加了一个名为“v2Folder”的文件夹,并向其中添加了 A v2.0.0.0,设置其“复制到输出目录” " 始终复制 3. 在 app.config 中添加了“探测路径”以指向带有 v2.0.0.0 DLL 的子文件夹

我想要的是在普通\bin\文件夹中看到A v1.0.0.0,在\bin\v2Folder中看到A v2.0.0.0,我希望当我运行我的Proj1.exe时,Proj1的旧代码仍然会调用A v1.0.0.0的方法,只有在调用Proj2实现的时候才调用A v2.0.0.0的方法。

问题是,当我构建我的解决方案时,v1.0.0.0 被 v2.0.0.0 取代,构建日志有类似“No way to resolve conflict between”A,Version=2.0.0.0,Culture=neutral, PublicKeyToken=blah”和“A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blah”。任意选择“A, Version=2.0.0.0, Culture=neutral, PublicKeyToken=blah”。

有人可以帮忙吗?

4

3 回答 3

5

即使两个 dll 版本具有相同的公共令牌也是可以实现的。

以下是实现此目的的步骤:

  • 确保将两个版本的dll复制到目标目录
    • 添加两个dll作为项目的内容项
    • 为两者启用本地副本
  • 确保在编译时会引用两个版本的dll
    • 在项目中添加两个dll作为引用
    • 禁用两者的本地副本

仅添加引用是不够的,因为只会复制较新的引用(即使您为两者都启用了本地复制)。这给出了一个像这样的项目树:

项目树

  • 确保在编译时可以区分两个版本的dll
    • 为至少一个引用添加别名

别名字段位置

  • 使用外部别名引用代码中的库(请参阅@drf响应

示例代码

此时您可以编译,但在运行时仍然存在问题。要解决这些问题:

自动生成绑定重定向复选框位置

  • 编辑app.config以添加assemblyBinding.
    • assemblyIdentity是相关的dll。
    • bindingRedirect将版本范围 ( oldVersion) 映射到固定版本 ( newVersion)。
    • codeBase将 a fixed 映射version到文件路径 ( href)。

bindingRedirect newVersion并且codeBase version必须匹配和匹配使用的dll的版本。

在这里,都是关于dll 程序集版本,而不是文件版本 app.config 示例

这是程序输出:

控制台输出

此 hack 源代码可在此处获得。

编辑:正如Sharpiro评论的那样,在构建项目时仍然会出现警告,这与这个msbuild bug有关,因为这个答案是一种解决方法。

于 2019-11-20T10:22:39.507 回答
2

使用该功能可以实现这一点extern alias。编译时,请包含 DLL 文件的别名,例如:

csc.exe ... /reference:AV1=v1.0.0.0/A.dll /reference:AV2=v2.0.0.0/A.dll

(这也可以在 Visual Studio 中通过更改aliases引用的属性来设置。)

在 cs 文件中,您可以extern alias用来引用命名空间:

extern alias AV1;
extern alias AV2;
// using statements

这允许您独立引用每个版本:

var v1foo = new AV1::Foo();
var v2foo = new AV2::Foo();

对于仅使用其中一个 DLL 的项目,您可以包含对所需版本的引用。

// ProjA cs file
extern alias AV1;
using Foo = AV1::Foo; // alternately, path to namespace
...
var foo = new Foo(); // from version 1 of library


// ProjB cs file
extern alias AV2;
using Foo = AV2::Foo; // alternately, path to namespace
...
var foo = new Foo(); // from version 2 of library

这允许在同一解决方案中独立引用 DLL 的两个版本。(MSDN 参考。)

于 2012-07-18T23:30:25.853 回答
0

将第 3 方 dll 版本 2.0 重命名为 A_2.dll,并添加对重命名的 dll 的引用。

于 2012-07-18T22:52:35.247 回答