dll組件版本兼容問題,是生產開發中常常遇到的問題,常見組件兼容問題如:Newtonsoft.Json,log4net等html
爲了節約你們時間,想直接看解決方法的,可直接點擊目錄三、4git
2.解決版本兼容前提markdown
4.指定某文件夾中的特定版本codeBase**gitlab
首先讓咱們簡單瞭解下程序引用的原理:visual-studio
當運行庫試圖解析對另外一個程序集的引用時,就開始進行定位並綁定到程序集的進程。詳細見:運行庫如何定位程序集測試
步驟以下:spa
簡單瞭解原理之後,常看法決兼容的方法.net
1)文件夾裏dll文件,右鍵->屬性
2)解決方案裏引用的dll,右鍵->屬性
利用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這個版本
經驗:
一、各版本之間是有代碼變化的,若是一個類庫用了某個組件10.0的A10方法,結果指向的8.0,8.0頗有可能尚未A10這個方法,天然項目中用到A10的地方會報錯。調試和查錯誤比較麻煩,編譯器會根據bin下面的dll版本與代碼來匹配調用方法和屬性提示錯誤,或者不提示錯誤。
二、代碼可控的地方,儘量的將版本更新中的廢棄方法改爲高版本的替代方法。
三、通常高版本多數是兼容低版本的方法,指向高版本報錯概率小些,固然也有特殊狀況。
方法一能解決不少項目中出現的版本問題,可是有時候仍是會遇到比較奇怪的兼容問題。
例如:log4net和Memcached.ClientLibrary中的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的低版本致使與高版本兼容問題
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建立測試頁面,測試代碼以下:
二、應用層,引用高版本log4net
WebApp引用log4net 2.0.8
最終項目狀況是:
三、運行結果
查看WebApp的bin文件夾下面的log4net版本是2.0.8,而Memcached.ClientLibrary組件用的log4net是1.2.10.0版本,因此報錯了。
注意
若是單獨編譯WebApp,bin下面是版本是2.8.0,若是單獨編譯ClassLibrary類庫,bin下面版本是1.2.10.0
一、bin下面添加log4net1.2.10.0文件夾,並將log4net.dll版本爲1.2.10.0放入到文件夾中,可重命名爲log4net1.2.10.0.dll。
二、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>
三、結果以下
經驗:
一、文件須要放在bin下面,並單獨創建個文件夾,注意:若不創建文件夾,直接將重命名的log4net1.2.10.0.dll扔到bin下會報錯,應該是探測方法是根據name尋找的。
二、ClassLibrary類庫在單獨編譯的時候,會將高版本的替換成低版本,會有可能報錯,能夠在開發中將其生成的dll不復制到bin下,設置是在引用的dll下右鍵,複製本地設置爲false,操做以下:
三、爲了能把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)
文章和觀點,有可能由於知識和閱歷的緣由,分析片面,請多諒解。