Net dll組件版本兼容問題
dll組件版本兼容問題,是生產開發中經常遇到的問題,常見組件兼容問題如:Newtonsoft.Json,log4net等
為了節約大家時間,想直接看解決方法的,可直接點擊目錄3、4
目錄
1.版本兼容問題的原因
2.解決版本兼容前提
3.指定特定版本bindingRedirect**
4.指定某文件夾中的特定版本codeBase**
版本兼容問題的原因
首先讓我們簡單了解下程序引用的原理:
當運行庫試圖解析對另一個程序集的引用時,就開始進行定位並綁定到程序集的進程。詳細見:運行庫如何定位程序集
步驟如下:
- 第 1 步:檢查配置文件(.config文件)
- 第 2 步:檢查以前引用的程序集
- 第 3 步:檢查全局程序集緩存
- 第 4 步:通過基本代碼或探測定位程序集
解決版本兼容前提
簡單了解原理以後,常見解決兼容的方法
1. 首先了解你要用那個dll,具體版本是什麽,查看版本方法:
1)文件夾裏dll文件,右鍵->屬性
2)解決方案裏引用的dll,右鍵->屬性
方法1、指定特定版本**
利用config的bindingRedirect指向特定版本組件
.config添加節點
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
解釋:
項目中所有項目、類庫引用0~10的Newtonsoft.Json版本,最終都指向到10這個版本
經驗:
1、各版本之間是有代碼變化的,如果一個類庫用了某個組件10.0的A10方法,結果指向的8.0,8.0很有可能還沒有A10這個方法,自然項目中用到A10的地方會報錯。調試和查錯誤比較麻煩,編譯器會根據bin下面的dll版本與代碼來匹配調用方法和屬性提示錯誤,或者不提示錯誤。
2、代碼可控的地方,盡可能的將版本更新中的廢棄方法改成高版本的替代方法。
3、一般高版本多數是兼容低版本的方法,指向高版本報錯幾率小些,當然也有特殊情況。
方法2、指定某文件夾中的特定版本
方法一能解決很多項目中出現的版本問題,但是有時候還是會遇到比較奇怪的兼容問題。
例如:log4net和Memcached.ClientLibrary中的log4net沖突的問題,本文以解決這一版本沖突問題為例介紹此方法的使用方法。
如果想直接看結果,請點擊解決方法
為啥會出現log4net版本兼容問題呢?
常見的組件是以name(名稱)、version(版本)、publicKeyToken(公鑰)三個組成,原因主要是由於log4net version 1.2.11與1.2.10的publicKeyToken不同所致。
可利用VS工具SN -T 組件文件名.dll查看公鑰。
log4net (≥ 1.2.11) 公鑰標記為 669e0ddf0bb1aa2a
log4net (= 1.2.10) 公鑰標記為 1b44e1d426115821
看log4net在發展過程中改過一次身份證,又有好多老版本的組件引用了log4net的低版本導致與高版本兼容問題
log4net版本兼容問題的樣例
1、創建項目,引用Memcached組件
WebApp為項目應用層,ClassLibrary為工具類庫,WebApp引用ClassLibrary項目,ClassLibrary通過nuget引入Memcached.ClientLibrary 1.0組件。
ClassLibrary創建類Testing.cs代碼如下:
public class Testing { public static void Init() { MemcachedClient mc = new MemcachedClient(); } }
WebApp創建測試頁面,測試代碼如下:
Testing.Init();2、應用層,引用高版本log4net
WebApp引用log4net 2.0.8
最終項目情況是:
3、運行結果
查看WebApp的bin文件夾下面的log4net版本是2.0.8,而Memcached.ClientLibrary組件用的log4net是1.2.10.0版本,所以報錯了。
註意
如果單獨編譯WebApp,bin下面是版本是2.8.0,如果單獨編譯ClassLibrary類庫,bin下面版本是1.2.10.0
處理log4net版本兼容問題
1、bin下面添加log4net1.2.10.0文件夾,並將log4net.dll版本為1.2.10.0放入到文件夾中,可重命名為log4net1.2.10.0.dll。
2、config添加
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" /> <codeBase version="1.2.10.0" href="bin/log4net1.2.10.0/log4net1.2.10.0.dll" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" /> </dependentAssembly> </assemblyBinding> </runtime>
3、結果如下
經驗:
1、文件需要放在bin下面,並單獨建立個文件夾,註意:若不建立文件夾,直接將重命名的log4net1.2.10.0.dll扔到bin下會報錯,應該是探測方法是根據name尋找的。
2、ClassLibrary類庫在單獨編譯的時候,會將高版本的替換成低版本,會有可能報錯,可以在開發中將其生成的dll不復制到bin下,設置是在引用的dll下右鍵,復制本地設置為false,操作如下:
3、為了能把log4net1.2.10.0.dll上傳到gitlab上面,可以在WebApp建立個相應文件夾,並設置復制到輸出目錄-始終復制,vs編譯時會自動將log4net1.2.10.0/log4net1.2.10.0.dll復制到bin下面
總結
希望通過此文章,幫助更多的人解決NET組件的版本兼容問題。
參考文章
https://www.cnblogs.com/shijun/p/3713830.html
https://blog.csdn.net/zfrong/article/details/6183353
https://docs.microsoft.com/zh-cn/previous-versions/dotnet/netframework-3.5/6bs4szyc(v%3dvs.90)
https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/yx7xezcf(v=vs.90)
文章和觀點,有可能因為知識和閱歷的原因,分析片面,請多諒解。
Net dll組件版本兼容問題