目錄
對.NET標準進行了解釋,說明了什麼時候可以使用替代方法,以及哪些替代方法可行。給出了這種替代方案的兩個例子。
介紹
許多開發人員都熟悉.NET Standard。顧名思義,它是.NET的標準,因爲.NET Framework不是唯一受支持的平臺。創建一個.NET Standard項目,使我們能夠編寫和編譯用於多個平臺的代碼。支持哪種平臺取決於您選擇的.NET Standard版本,但總體列表很長:.NET Core,.NET Framework,Mono,Xamarin.iOS,Xamarin.Mac,Xamarin.Android,Universal Windows Platform和Unity。
如果您的代碼確實是通用的,那麼這很好,例如,如果您創建客戶端程序包或實現數學模型。但是,一旦某些代碼或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的忠實擁護者。但是,每個解決方案都有我提到的缺點。