.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的忠实拥护者。但是,每个解决方案都有我提到的缺点。

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