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號