1. 程式人生 > >Net dll組件版本兼容問題

Net dll組件版本兼容問題

更多 red 程序集 lse 時間 開始 版本沖突 run details

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組件版本兼容問題