dotnet core TargetFramework 解析順序測試
dotnet core TargetFramework 解析順序測試
Intro
現在 dotnet 的 TargetFramework
越來越多,拋開 .NET Framework 不談,如果一個類庫支援多個 TargetFramework
應用實際運行的時候會使用哪個版本的 API 呢,之前一直都是想當然的自以為是了,於是想測試一下實際解析是怎麼樣的,來看下面的示例吧
Sample
Library Sample
首先來看類庫示例項目:
項目文件如下:
類庫提供了多個 TargetFramework
的支援:
netstandard2.0
netcoreapp2.1
netstandard2.1
netcoreapp3.1
net5.0
net6.0
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1;netstandard2.1;netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
</PropertyGroup>
</Project>
類庫里只提供了一個類,只有一個用於測試的方法,方法實現如下:
public class Test
{
public static string GetResult()
{
var result = string.Empty;
#if NET6_0
result = "NET6.0";
#elif NET5_0
result = "NET5.0";
#elif NETCOREAPP3_1
result = "NETCOREAPP3_1";
#elif NETCOREAPP3_0
result = "NETCOREAPP3_0";
#elif NETCOREAPP2_1
result = "NETCOREAPP2_1";
#elif NETSTANDARD2_1
result = "NETSTANDARD2_1";
#elif NETSTANDARD2_0
result = "NETSTANDARD2_0";
#endif
return result;
}
}
通過條件編譯在不同的 TargetFramework
下返回不同的值以測試實際執行的程式碼
Executable Sample
接著看一個可執行的 Console 應用,項目文件示例如下:
Console
應用支援的 TargetFramework
如下:
- netcoreapp2.0
- netcoreapp2.1
- netcoreapp3.0
- netcoreapp3.1
- net5.0
- net6.0
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
<NoWarn>;NETSDK1138</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TestClassLibrary\TestClassLibrary.csproj" />
</ItemGroup>
</Project>
因為 netcoreapp2.0
和 .netcoreapp3.0
已經不再支援,如果直接使用會得到一個 Warning:
所以在項目文件中配置了 <NoWarn>;NETSDK1138</NoWarn>
來忽略這個警告
測試程式碼很簡單,直接調用類庫示例中的測試方法:
Console.WriteLine(Test.GetResult());
Console.WriteLine("Hello World!");
Console.ReadLine();
Test Output
接著我們就來測試吧,先思考一下吧,不同的 TargetFramework
輸出的結果分別是什麼呢?
net6.0
net5.0
netcoreapp3.1
netcoreapp3.0
netcoreapp2.1
netcoreapp2.0
More
從上面的測試結果其實就能夠大概看出來,多個 TargetFramework
的解析順序,可執行應用程式首先會匹配與當前運行的 TargetFramework
相符的框架,如果沒有與當前運行的 TargetFramework
相符的框架,則會fallback 到低版本的 .NET 框架上,優先選擇高版本的框架,如果當前運行的框架版本是 net6.0
,但是類庫不支援 net6.0
,則會使用 net5.0
,如果類庫不支援 net5.0
則會使用 netcoreapp3.1
以此類推。
如果既有 .NET Core 的框架支援又有 .NET Standard 的支援,則會優先使用 .NET Core 框架,沒有可用的 .NET Core 框架的話再開始看類庫支援的 .NET Standard 的支援,優先選擇當前框架支援的高版本的 .NET Standard 框架
最後擴展一下,引用單個類庫是上面這樣的,如果類庫引用了類庫,那又會如何呢
測試項目結構如下,測試項目基於 .NET6.0
,引用了一個基於 netstandard2.0
/netstandard2.1
的類庫項目 ClassLibrary1
,而 ClassLibrary1
引用了另外一個基於netstandard2.0
/netstandard2.1
/netcoreapp2.1
的類庫項目,測試方法和上面的差不多,測試項目調用 ClassLibrary1
中的測試方法(實際調用了 ClassLibrary2
中的測試方法)
ConsoleApp(NET6.0
)
- ClassLibrary1(
netstandard2.0
/netstandard2.1
)- ClassLibrary2(
netstandard2.0/netstandard2.1/netcoreapp2.1
)
- ClassLibrary2(
輸出結果如下:
從上面的結果來看,實際的解析結果運行結果都是根據最終執行到的類庫結合應用當前運行框架來決定使用哪個版本的程式碼的
References
- //github.com/WeihanLi/SamplesInPractice/tree/master/UnexpectedSamples
- //docs.microsoft.com/en-us/dotnet/core/tutorials/libraries#how-to-target-the-net-framework