一个项目引用不用版本dll

问题描述

一个项目引用不同版本的同一dll,会引发以下报错:

未能加载文件或程序集“xxx, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxxxxx”或它的某一个依赖项。系统找不到指定的文件 

这里来解决项目中同一dll的多版本问题。

解决方式

通过配置web.config配置文件(app.config或web.config)增加配置节点

不同场景有不同的解决方式,下面说明

1. 场景一   以高版本兼容

例如:新旧项目都引用Newtonsoft.Json,但是不同版本。需要以最高版本兼容。 

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
      <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>           
    </dependentAssembly> 
  </assemblyBinding>
</runtime>

2. 场景二   同一dll两种版本共存

例如:项目自己引用log4net.dll 版本1.2.13.0 。添加第三方某个dll,第三方依赖log4net.dll版本1.2.9.0,项目中需要两种版本共存。

这里还分两种情况,dll的publicKeyToken相同还是不同 (publicKeyToken查询见说明1

publicKeyToken相同,配置方法:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />
      <codeBase version="1.2.13.0" href="bin\log4netdll\1_2_13\log4net.dll" />  
      <codeBase version="1.2.9.0" href="bin\log4netdll\1_2_9\log4net.dll" />           
    </dependentAssembly>       
  </assemblyBinding>       
</runtime>

publicKeyToken不同,配置方法:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />
      <codeBase version="1.2.13.0" href="bin\log4netdll\1_2_13\log4net.dll" />   
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="log4net" publicKeyToken="b32731d11ce58905" />
      <codeBase version="1.2.9.0" href="bin\log4netdll\1_2_9\log4net.dll" />
    </dependentAssembly>
  </assemblyBinding>    
</runtime>

 

说明

1.publicKeyToken获取方式
使用vs的Tools Command Prompt命令行工具,输入:SN -T "path",例如:

C:\Program Files (x86)\Microsoft Visual Studio 11.0>SN -T "D:\project\liberary\External\log4net.dll"

Microsoft(R) .NET Framework 强名称实用工具 版本 4.0.30319.17929
版权所有(C) Microsoft Corporation。保留所有权利。

公钥标记为 b32731d11ce58905

参考文献

msdn对配置详解:  https://msdn.microsoft.com/zh-cn/library/twy1dw1e

 

转载于:https://my.oschina.net/u/2438432/blog/917764

<think>好的,我现在需要解决用户的问题:如何在同一个C#项目中正确引用多个同名DLL文件?这个问题看起来有点挑战性,因为通常情况下,如果两个DLL文件名相同,直接引用会导致冲突。用户提到他们有三个项目a、b、c,其中a依赖b,b依赖c,生成顺序是c->b->a,结果c和b的DLL都被放到了a的bin目录下。现在遇到了同名DLL的问题。 首先,我需要回忆一下C#中如何处理程序集引用。通常,当项目引用其他项目DLL时,编译时会将这些依赖项复制到输出目录(比如bin/Debug)。如果两个不同DLL同名,即使它们来自不同的路径,也会被覆盖,导致运行时错误。 接下来,用户的情况可能是有两个不同DLL,但名称相同,比如都叫“MyLibrary.dll”,但版本不同或内容不同。这时候直接引用会导致冲突。 解决方案方面,首先想到的是使用别名。C#允许为程序集引用指定别名,这样在代码中可以通过别名来区分不同DLL。例如,引用一个DLL时使用别名“Alias1”,第二个使用“Alias2”,然后在代码中使用extern alias Alias1;来引入对应的命名空间。 步骤大概是这样的:在Visual Studio中,引用每个DLL,然后在属性面板中设置别名。默认别名是“global”,可以改为自定义的。然后在代码文件顶部使用extern alias语句来声明,之后就可以通过别名访问不同的类型。 不过,用户可能需要注意,如果这些同名DLL中的类型有相同的命名空间和类名,那么即使使用别名,也需要在代码中明确指定别名,否则编译器无法区分。例如,Alias1::MyNamespace.MyClass和Alias2::MyNamespace.MyClass。 另外,另一个可能的解决方案是修改生成路径,将不同DLL放在不同的子目录中,然后通过配置文件指定探测路径。例如,在App.config中使用<probing privatePath="subdirectory1;subdirectory2" />,让运行时从这些子目录加载DLL。但这种方法需要确保DLL的文件名不同,否则还是会有冲突,因为运行时按文件名加载。 但用户的问题是同名DLL,所以修改路径可能不够,除非同时重命名DLL。不过重命名DLL可能会影响其内部元数据,比如强名称等,这可能有风险,需要重新签名或者确保没有强名称验证。 还有可能需要考虑绑定重定向,在App.config中使用assemblyIdentity和codeBase来指定不同版本DLL的路径。不过这也适用于不同版本但同名的情况,但同样需要DLL不同版本号或其他标识信息。 回到用户的案例,他们可能是在项目引用中遇到了自动复制依赖项导致同名DLL被覆盖的问题。例如,项目b引用了c,生成时把c的DLL复制到b的bin,然后a引用b,又把b和c的DLL复制到a的bin。如果c本身引用了另一个同名的DLL,或者用户手动添加了同名DLL,就会出问题。 因此,正确的步骤应该是: 1. 对每个同名DLL引用,在项目中使用别名。例如,在引用时,属性里设置别名。 2. 在代码中使用extern alias来区分不同DLL中的类型。 3. 确保生成后的DLL不会被覆盖,可能需要调整生成路径或使用不同的文件名。 另外,需要注意如果这些DLL是强签名的,可能需要处理公钥令牌的问题,或者确保别名正确应用。 注意事项包括:确保所有引用DLL版本兼容,避免运行时类型转换错误;在团队开发中统一别名设置,避免代码混乱;以及处理可能出现的元数据冲突。 现在,需要验证这些思路是否正确。比如,查看C#文档关于extern alias的部分,确认是否支持这种方式。根据微软文档,确实可以通过extern alias来解决同名程序集的问题。因此,这应该是可行的解决方案。 总结步骤: 1. 在项目中为每个同名DLL添加引用,并设置不同的别名。 2. 在代码中使用extern alias声明这些别名。 3. 通过别名限定符访问不同类型。 此外,如果DLL文件名可以修改,重命名文件可能是另一种方法,但需要确保所有引用都更新,并且DLL内部没有依赖其原名称的情况。 最后,还要提醒用户注意版本管理和依赖冲突,避免在运行时加载错误的程序集。</think>在C#项目引用多个同名DLL时,需通过**程序集别名**和代码命名空间限定来解决冲突。以下是具体步骤和注意事项: --- ### **解决方案步骤** 1. **为DLL引用设置别名** - 在Visual Studio的解决方案资源管理器中,右键目标DLL引用 → 选择“属性” → 在“别名”字段中设置自定义别名(如`LibV1`、`LibV2`)[^1]。 - 默认别名为`global`,需改为唯一值避免冲突。 2. **在代码中声明别名** 在需要使用DLL的代码文件顶部添加`extern alias`指令: ```csharp extern alias LibV1; // 对应第一个DLL的别名 extern alias LibV2; // 对应第二个DLL的别名 ``` 3. **通过别名访问类型** 使用`别名::命名空间.类名`的语法区分同名类型: ```csharp var obj1 = new LibV1::MyNamespace.MyClass(); var obj2 = new LibV2::MyNamespace.MyClass(); ``` --- ### **注意事项** 1. **DLL元数据兼容性** - 若DLL包含强名称(Strong Name),需确保公钥和版本信息不同,否则别名可能失效。 - 避免DLL内部类型因完全限定名相同导致冲突(即使使用别名)。 2. **生成目录管理** - 若DLL自动复制到输出目录(如`bin`),需通过项目配置调整生成路径,或手动控制文件复制逻辑。 3. **配置绑定重定向(可选)** 在`App.config`中指定不同版本的探测路径,但需配合程序集版本差异: ```xml <configuration> <runtime> <assemblyBinding> <dependentAssembly> <assemblyIdentity name="MyLibrary" publicKeyToken="..." culture="neutral"/> <codeBase version="1.0.0.0" href="LibV1/MyLibrary.dll"/> <codeBase version="2.0.0.0" href="LibV2/MyLibrary.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration> ``` 4. **统一团队开发规范** - 别名命名需在团队内统一,避免代码维护混乱。 --- ### **示例场景** 假设项目需同时引用`MyMath.v1.dll`和`MyMath.v2.dll`(均包含`Calculator`类): ```csharp extern alias MathV1; extern alias MathV2; public class Program { static void Main() { var calc1 = new MathV1::MyMath.Calculator(); var calc2 = new MathV2::MyMath.Calculator(); } } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值