最近公司有將Windows下運(yùn)維服務(wù)節(jié)點(diǎn)移植到Linux系統(tǒng)下的動(dòng)作,而在代碼不做過大改動(dòng)的情況下,最合適的方案貌似就剩下了跨平臺(tái)移植。因?yàn)橹暗倪\(yùn)維服務(wù)節(jié)點(diǎn)就是基于.NET Framework寫的,所以考慮到微軟的跨平臺(tái)方案,貌似只有.Net Core了。本文把移植過程中的遇到的難點(diǎn)(.Net Core小白,第一次接觸,所以幾乎都是難點(diǎn))記錄下來,做個(gè)整理。
什么是.Net Core跨平臺(tái)?
.NET Core?是開放源代碼通用開發(fā)平臺(tái),由 Microsoft 和 .NET 社區(qū)在?GitHub?上共同維護(hù)。?它支持跨平臺(tái)(支持 Windows、macOS 和 Linux),并且可用于生成設(shè)備、云和 IoT 應(yīng)用程序。
這個(gè)跨平臺(tái)其實(shí)是“半跨平臺(tái)”??紤]到Windows和Linux的平臺(tái)特殊性(比如,Windows有注冊(cè)表而Linux沒有),所以,不可能指望把整套項(xiàng)目改變目標(biāo)框架就實(shí)現(xiàn)跨平臺(tái)運(yùn)行,項(xiàng)目多多少少還是要改滴。微軟的工程師考慮到了這一點(diǎn),所以推出了一個(gè)分析器,這個(gè)軟件的目的就是分析你當(dāng)前的項(xiàng)目有百分之幾可以不用任何改動(dòng)移植到.Net Core。這個(gè)分析器的名字叫.NET Portability Analyzer, 在VS 2017 "工具"-》"擴(kuò)展和更新"中可以搜索到并安裝。

用法也很簡(jiǎn)單。只要在你的解決方案管理器中右鍵你的項(xiàng)目,然后選擇"Analyze Project Portability"(無外部引用)或者"Analyze Project Portability (with project references)"(有外部引用),然后軟件會(huì)為你生成一個(gè)Results文件的彈窗,然后打開xml文件,就可以看到移植的可能性。

在評(píng)估了項(xiàng)目遷移的可行性以后,下面就是正式的項(xiàng)目遷移了。
正式遷移
.Net Core只支持兩種客戶端模式的開發(fā):控制臺(tái)程序(Console App)和類庫(kù)(dll)。也就是說,如果你的項(xiàng)目是WPF、Winform、WCF程序的話,對(duì)不起,你的項(xiàng)目不適合跨平臺(tái)移植,老老實(shí)實(shí)的寫Linux下原生應(yīng)用吧。當(dāng)然,我們的項(xiàng)目是基于控制臺(tái)的,所以有移植的可能性。
首先,打開VS2017,新建一個(gè)Visual C# -》.Net Core,選擇控制臺(tái)程序項(xiàng)目。然后將里面的.cs文件代碼刪除,然后項(xiàng)目上右鍵選擇"添加"-》"現(xiàn)有項(xiàng)",然后找到你準(zhǔn)備遷移的項(xiàng)目中的.cs文件,然后在"添加"按鈕的下拉框下選擇"添加為鏈接"。為什么要選擇這一項(xiàng)呢?因?yàn)檫x擇這個(gè)的時(shí)候,不需要復(fù)制原有項(xiàng)目文件,而且還能跟復(fù)制項(xiàng)目文件起到一樣的效果。
剛才說過,代碼不是100%可以被移植到Linux平臺(tái)的。也就是說,里面有一些代碼是平臺(tái)特有的,這時(shí)候就要使用條件編譯了。簡(jiǎn)單的說就是if是.Net Core的程序,執(zhí)行這些平臺(tái)的特殊操作,else執(zhí)行項(xiàng)目原有的操作邏輯。使用的宏定義為
#if NETCOREAPP2_1
? ? [PlatformBehavior]
#else
? ? [ServiceBehavior]
#endif
也就是說,在你項(xiàng)目中涉及到操作系統(tǒng)底層相關(guān)的API時(shí),你可以使用這個(gè)宏定義進(jìn)行條件編譯,從而保證項(xiàng)目在兩個(gè)平臺(tái)上都可以正常運(yùn)行,從而實(shí)現(xiàn)跨平臺(tái)。
在跨平臺(tái)時(shí),不得不提的就是.Net Core和項(xiàng)目原本框架.Net Framework的關(guān)系。引用官方文檔的原話:
.NET Core and the .NET Framework have (for the most part) a?subset-superset?relationship. .NET Core is named "Core" since it contains the core features from the .NET Framework, for both the runtime and framework libraries. For example, .NET Core and the .NET Framework share the GC, the JIT and types such as String and List<T>. We'll continue improving these components for both .NET Core and .NET Framework.
.NET Core was created so that .NET could be open source, cross platform and be used in more resource-constrained environments. We have also published a subset of the .NET Reference Source under the MIT license, so that you and the community can port additional .NET Framework features to .NET Core.
從官方文檔可以看出,.NET Core 是從 .NET Framework 演化而來,有點(diǎn)像父類-子類關(guān)系,而不是子集關(guān)系。這意味著什么?很多.NET Framework的API在.Net Core中是無法使用的!


所以說,這就是最難辦的地方。目前,我的解決方式有三個(gè):
1)在Nuget中下載對(duì)應(yīng)的包,舉個(gè)例子:
原項(xiàng)目中用到了System.Management中的相關(guān)API,但是在.Net Core中并沒有直接提供System.Management的類庫(kù),所以從Nuget中下載下來就可以直接使用原本只能在.Net Framework中的關(guān)于System.Management相關(guān)API。
2)如果引用第三方,那么對(duì)不起,找到第三方庫(kù)的源代碼,自行編譯.Net Core版本的,舉個(gè)例子:
原項(xiàng)目中用到了agsXmpp,是基于.Net Framework 4.0的,那么找到它的源代碼,按照代碼移植和條件編譯的方法編譯出.Net Core版本的。
3)在https://github.com/dotnet/corefx/wiki/ApiCompat中尋找API的使用方式和平臺(tái)特性。
如果這些都不可行的話,那么需要考慮這個(gè)項(xiàng)目中的這些功能是否有跨平臺(tái)的必要性。如果勢(shì)必需要,可以考慮前面所說的用平臺(tái)的原生開發(fā)來代替跨平臺(tái)。
先寫到這里吧,后面還有很多遇到的難點(diǎn),往后一一整理吧,謝謝!