C# 引用不同版本dll
问题描述
一个项目引用不同版本的同一dll,会引发以下报错:
未能加载文件或程序集“xxx, Version=x.x.x.x, Culture=neutral, PublicKeyToken=xxxxxxxxxxxx”或它的某一个依赖项。系统找不到指定的文件
解决方式
方式1:通过配置文件
配置文件一般在你的应用程序项目下,形如(app.config或web.config),如果没有可以自己添加一个;我认为在非主程序的项目中添加xxx.config应该是没有用的
然后在配置文件中,增加配置节点;然而,不同场景有不同的解决方式,下面说明。
场景一 以高版本兼容
例如:新旧项目都引用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>
场景二 同一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
方式2:通过代码
可以在主程序入口函数中添加程序集加载失败的事件订阅;当程序集加载失败后,可以自己指定从哪个目录加载程序集文件。
下面以WPF程序为例,在app.xaml.cs的构造函数中加入如下事件订阅:
// 订阅程序集解析失败事件
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
然后在事件响应函数中做逻辑处理
/// <summary>
/// 当CLR无法找到程序集时触发此方法
/// </summary>
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    // 获取程序集名称
    string assemblyName = new AssemblyName(args.Name).Name;
    // 定义你要查找的子目录
    string subDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SubDirectory");
    // 构造完整路径
    string assemblyPath = Path.Combine(subDirectory, $"{assemblyName}.dll");
    // 如果文件存在,则加载它
    if (File.Exists(assemblyPath))
    {
        return Assembly.LoadFrom(assemblyPath);
    }
    // 否则返回 null 表示仍然找不到
    return null;
}
参考文献
.Net Framework中的AppDomain.AssemblyResolve事件的常见用法、问题,以及解决办法
msdn对配置详解
引用不同版本dll
                    
                
                
            
        
浙公网安备 33010602011771号