.NET Standard,有哪些替代方案?

目錄

介紹

背景

使用代碼

興趣點


.NET標準進行了解釋,說明了什麼時候可以使用替代方法,以及哪些替代方法可行。給出了這種替代方案的兩個例子。

介紹

許多開發人員都熟悉.NET Standard。顧名思義,它是.NET的標準,因爲.NET Framework不是唯一受支持的平臺。創建一個.NET Standard項目,使我們能夠編寫和編譯用於多個平臺的代碼。支持哪種平臺取決於您選擇的.NET Standard版本,但總體列表很長:.NET Core.NET FrameworkMonoXamarin.iOSXamarin.MacXamarin.AndroidUniversal Windows PlatformUnity

如果您的代碼確實是通用的,那麼這很好,例如,如果您創建客戶端程序包或實現數學模型。但是,一旦某些代碼或NuGet程序包依賴於某些特定平臺,.NET標準將無濟於事。.NET Standard是標準的,而不是特定於平臺的。那麼在這種情況下如何針對多個平臺呢?

背景

如果您有.NET開發經驗,最好具有多個平臺或平臺的多個版本,這將對您有所幫助。

使用代碼

第一步非常簡單:在項目文件中定位TargetFrameworks 而不是TargetFramework。既然如此,我們無論如何都要做。

<PropertyGroup>
  <TargetFrameworks>netcoreapp3.1;netcoreapp2.1</TargetFrameworks>
</PropertyGroup>

現在,我們開始編碼一個dummy類,看看它是否有效。

public class DummyClass : IAsyncDisposable
{
    public void DoSomething()
    {
        Console.WriteLine("Something needs is done");
    }

    public void Dispose()
    {
        Console.WriteLine("Object is disposed");
    }

    public async ValueTask DisposeAsync()
    {
        Console.WriteLine("Object is disposed asynchronously");
    }
}

我們在這裏遇到編譯器錯誤:

引用:

錯誤CS0246:找不到類型或名稱空間名稱“IAsyncDisposable”(您是否缺少using指令或程序集引用?)

錯誤是正確的。我們正在嘗試以非最新.NET Core版本爲目標。但是對於.NET Core 3.1,不應發生此類錯誤。我們需要在我們的代碼中解釋哪一部分是平臺特定的:

public class DummyClass
    #if NETCOREAPP3_1
    : IAsyncDisposable
    #endif
{
    public void DoSomething()
    {
        Console.WriteLine("Something needs is done");
    }

    public void Dispose()
    {
        Console.WriteLine("Object is disposed");
    }

    #if NETCOREAPP3_1
    public async ValueTask DisposeAsync()
    {
        Console.WriteLine("Object is disposed asynchronously");
    }
    #endif
}

通過使用該#if指令,很明顯某些代碼是特定於.NET Core 3.1的。可以爲兩個平臺編譯其他代碼。

也可以添加特定於平臺的NuGet軟件包。它是這樣工作的:

<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1'">
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.4" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1'">
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="2.1.3" />
</ItemGroup>

添加一個Condition可確保爲正確的平臺解決正確的依賴性。這種方法有效,但存在以下問題:

  • 您需要手動更改csproj文件。
  • 添加的平臺越多,csproj文件就越複雜。
  • 添加的平臺越多,代碼就越複雜。

從可維護性的角度來看,這可能不是您想要的情況。這就是爲什麼需要解釋這種方法的替代方法:具有部分類的共享項目。第一步是創建一個共享項目,這只是Visual Studio中可用的項目類型。在共享項目中,我們添加了一個部分類,該部分類僅包含預期將針對我們要定位的每個平臺進行編譯的代碼。這裏是:

public partial class DummyClass : IDisposable
{
    public void DoSomething()
    {
        Console.WriteLine("Something needs is done");
    }

    public void Dispose()
    {
        Console.WriteLine("Something is disposed");
    }
}

共享項目無法編譯,但是共享項目內部的代碼可以編譯。因此,我們需要在.NET Core 2.1項目中引用它。如果您以前從未使用過共享項目,則可以通過這種方式添加此類參考。由於IAsyncDisposable接口不存在,因此將編譯.NET Core 2.1項目。但是對於.NET Core 3.1項目,我們需要它。因此,我們也在那裏添加了一個局部類。

public partial class DummyClass : IAsyncDisposable
{
    public async ValueTask DisposeAsync()
    {
        Console.WriteLine("Object is disposed asynchronously");
    }
}

看來我們剛剛解決了上述問題:

  • 無需手動更改項目文件。
  • 更多平臺僅意味着更多項目。項目文件都很簡單。
  • 代碼文件簡短

但是,這種方法也存在一個問題:還有更多項目需要維護。此外,您無法從共享項目生成NuGet包。如果您對兩種解決方案的示例都感興趣,請從GitHub下載代碼。

興趣點

共享項目在Xamarin開發的世界中特別受歡迎,但也可以用於其他目的。在許多公司中,初級開發人員被告知複製代碼是一件壞事,因爲它會使維護代碼變得更加困難。但是,我們經常忘記告訴他們的是,共享項目具有相同的效果(在不同項目中編譯相同的代碼),但沒有缺點(該代碼只需要作爲一個項目的一部分保存在一個文件中)。我成爲Shared Projects的忠實擁護者。但是,每個解決方案都有我提到的缺點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章