dotnet core TargetFramework 解析順序探索

WeihanLi發表於2021-02-22

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:

EOL-warning

所以在專案檔案中配置了 <NoWarn>;NETSDK1138</NoWarn> 來忽略這個警告

測試程式碼很簡單,直接呼叫類庫示例中的測試方法:

Console.WriteLine(Test.GetResult());

Console.WriteLine("Hello World!");
Console.ReadLine();

Test Output

接著我們就來測試吧,先思考一下吧,不同的 TargetFramework 輸出的結果分別是什麼呢?

net6.0

net6.0

net5.0

net5.0

netcoreapp3.1

netcoreapp3.1

netcoreapp3.0

netcoreapp3.0

netcoreapp2.1

netcoreapp2.1

netcoreapp2.0

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)

輸出結果如下:

從上面的結果來看,實際的解析結果執行結果都是根據最終執行到的類庫結合應用當前執行框架來決定使用哪個版本的程式碼的

References

相關文章