1. 程式人生 > >.Net Standard擴充套件支援例項分享

.Net Standard擴充套件支援例項分享

  上篇(.Net基礎體系和跨框架開發普及)介紹了.Net當前生態下的大概情況,也分享了簡單實現的過程,這篇文章就是講解我的OSS.Common專案擴充套件.Net Standard 支援的過程,主要集中在:方案的選擇,移植檢測,移植過程,常見問題的解決思路,以及nuget的打包部署這幾個方面。

  在開始之前簡單介紹下OSS.Common專案的涉及的內容,方便了解後邊所遇到的問題。這個類庫是相對簡單的一個基礎類庫,提供主要有以下的內容:1. 基礎使用者系統裝置資訊實體定義,2. 主流加解密方案實現(md5,aes,sha1,hmacsha1), 3.  常規實體DTO轉化,靜態擴充套件方法(時間,字串等等處理), 4. 基礎日誌,快取,非同步輔助靜態類及預設方案實現(採用了簡單Provider模式,使用者可以註冊自己的實現方案), 5. 全域性結果,分頁實體定義。  其主要作用就是完成對常見碎化方法的收集規整,方便在業務邏輯中減少不必要的消耗,瞭解之後我們進入具體的擴充套件過程。

  一. 方案的選擇

  這個其實在上篇文章中已經做了介紹,當前.net core ,.net Framework,mono for Xarmain等都有自己的執行時,雖然使用的都是C#語法,但是類庫在不使用可移植或者標準庫的前提下不能直接互相呼叫。隨著.net standard 2.0的即將推出,.net core(asp.net core) 的應用場景會越來越普遍,對舊有專案的相容需求會越來越強烈,oss.common也是遇到這個問題,所以我將對它進行.net standard支援的擴充套件。

  由於當前專案現在在好幾個.net framework的專案中還在使用,為了舊專案中對net45的版本的支援不能丟失,所以我會保留兩套解決方案,一個為.net Standard 提供支援,一個為.net framework使用,兩個類庫專案,共享同一套程式碼檔案,針對Framework特有功能通過條件編譯來控制。github上目錄結構已更新,歡迎檢視。

  二. 移植檢測

  在移植之前我們需要對移植有個大概評估,瞭解需要程式碼改動的覆蓋面積,確定程式碼的可移植性,這裡推薦使用微軟官方提供的移植檢測工具(ApiPort),或者使用它的VS擴充套件。這裡我使用的是vs外掛,安裝完外掛之後,開啟解決方案,檢視右鍵選單會有如下兩個選項:

  首先,點選第二個選項,配置要檢測的移植對比版本,如下圖:

  完成對應的檢測版本之後點選確定,點選第一個選項,執行分析過程,會生成html和xsl兩種報表,html報表介面如下所示:

 報表中會給出對應版本的介面覆蓋情況,以及相關的建議,可以說是比較詳細了。

  三.移植過程

  經過上邊的檢測,可以看出oss.common專案 在.net standard1.4下,大概超過20%的程式碼不能直接提供支援,我看了一下,主要集中在涉及配置,快取,反射等特有屬性相關程式碼中,這個還算在預期之中,不過看到一堆的紅叉叉還是一陣頭疼,沒辦法,自己的類庫,哭著也要碼完,下邊介紹下移植的步驟。

  1. 新增專案檔案

  為了專案直觀和方便管理,我將原來的OSS.Common類庫修改名稱為OSS.Common.NET45,新建一個OSS.Common的標準庫專案,兩個專案檔案放在同一目錄下,說明一下,vs2015如果要建標準庫專案需要先建可移植類庫,在類庫屬性頁修改,如果不清楚請看上一篇文章介紹。

  這個時候如果你直接生成OSS.Common.NET45的專案,是會出現報錯的,哪怕你沒有做任何實際的程式碼的操作,主要是因為新增可移植類庫需要project.json的檔案進行依賴管理,當他們在同一目錄下時,nuget會把project.json中的依賴預設執行還原操作,雖然你當前是在生成OSS.Common.NET45專案,沒辦法,就是這麼傻,如果你遇到了這個錯誤,在當前目錄中再建一個對應當前專案檔案的project.json檔案就好了,這裡我添加了OSS.Common.Net45.project.json檔案,檔案中新增如下程式碼:

{
"frameworks": {
"net45": {}
},
"runtimes": {
"win": {}
}
}

  2. 程式碼整合

  新建好對應的解決方案之後,把程式碼檔案附件到新建的標準庫下,這個時候直接生成會有很多錯誤,這個時候我們就需要祭出條件編譯這個大招了,因為以後主要是維護標準庫,所以我在舊NET45的舊專案上新建了NETFW的條件編譯符號 ,剩下的就是一個個錯誤完善了。

  在處理相容的過程中,主要會面臨這幾個問題,1. 標準庫完全不支援   2.  標準庫和Framework的呼叫方法不一樣, 3. 可以間接完成標準庫的實現

  這裡我把我遇到的情況各舉一個例子供大家參考:

  1.  標準庫完全不支援,這個最典型的就是快取模組,在.net standard下,System.Runtime.Caching類庫完全被移除了,沒辦法,只能使用#if NETFW 完全把Module模組下的預設Cache實現給遮蔽了,只能在Framework下才能使用預設實現(本來打算自己實現一個快取類的,不過發現可能會帶來不可預知bug,作廢)。

  2. 標準庫和Framework的呼叫方法不一樣,舉個例子就是Type型別下的IsEnum屬性,在net standard下需要.gettypeinfo().IsEnum才可以,舉例程式碼:

#if NETFW
if (!enType.IsEnum)
#else
if (!enType.GetTypeInfo().IsEnum)
#endif

  3. 可以間接完成標準庫的實現,這常見的如 list的ConvertAll方法,在Framework下有預設實現的,標準庫下是沒有的,這裡我在ConvertExtention類自己定義了個一個:

#if !NET40
public static List<TResult> ConvertAll<TPara, TResult>(this List<TPara> list, Func<TPara, TResult> func)
{
if (list == null)
return null;
var resultList = new List<TResult>(list.Count);
list.ForEach(e => resultList.Add(func(e)));
return resultList;
}
#endif

 當然還會有其他的一些問題,不過還好,基本都已經解決,如果有不清楚的可以去下載oss.common程式碼自行檢視

  四. nuget打包部署

  這個相對簡單,在兩個解決方案中分別生成對應的dll,在lib資料夾中分別新增net45 和 netstandard1.4 資料夾新增對應的dll就行。

需要注意的一點就是,最好添加個各自的依賴,舉個例子,標準庫的Hmacsha1加密演算法在“System.Security.Cryptography.Algorithms” dll程式集下,如果在呼叫專案中沒有引用這個dll,生成是不會報錯的,但是當代碼執行呼叫的時候就會彈出程式集未找到的錯誤,當然如果發現這個問題也可以通過nuget線上安裝命令(install-package)安裝。

  給大家看下我的nuget檔案配置:

如有其它疑問,歡迎關注公眾號(osscoder):