用C#实现跨平台API

请参阅如何根据C#提供跨平台API,您可以在Universal Windows平台应用程序(UWP),Xamarin.ios,Xamarin.Android,Xamarin.Forms,ASP.NET甚至您的Classic .NET WPF应用程序中消耗。在我的最后一个 邮政 我展示了如何在具有依赖注入的便携式类库中使用平台特定的库和代码。当您开发自己的应用程序时,这种方法很棒,但是当您想向同事/开发人员提供库时,它会出现一些Quirky,因为您强制通过依赖注入来设置自己的库。但是当然,另一种方法可以整理地封装您的实现细节,同时仍然为PCL代码提供平台特定功能。

此博客文章中的库将为UWP,Xamarin.ios和Xamarin.Android应用提供的OS版本。

设置库

图书馆由四个项目组成:

  • Osversion.Core.
  • Osversion.uwp.
  • Osversion.Droid.Droid.
  • Osversion.ios.

关于所有项目有点特别的一件事是所有默认命名空间和装配名都具有相同的名称。

namespacebinaryname.

在每个项目中,我们实施 SystemInformationHandler.cs. 类,在PCL上,我们只需实施一个存根:

public class SystemInformationHandler
{
    #region Implementation of ISystemInformationHandler

    public static string OSVersion => "Gnabber";

    #endregion
}

对于其他平台,例如UWP,我们将调用UWP特定的API:

public class SystemInformationHandler
{
    public static string OSVersion
    {
        get { return OsVersionString(); }
    }

    private static string OsVersionString()
    {
        string sv = AnalyticsInfo.VersionInfo.DeviceFamilyVersion;
        ulong v = ulong.Parse(sv);
        ulong v1 = (v & 0xFFFF000000000000L) >> 48;
        ulong v2 = (v & 0x0000FFFF00000000L) >> 32;
        ulong v3 = (v & 0x00000000FFFF0000L) >> 16;
        ulong v4 = (v & 0x000000000000FFFFL);

        return $"Windows {v1}.{v2}.{v3}.{v4}";
    }
}

因此,最后,我们在PCL和我们旨在支持的每个平台中实现了PCL和特定类的泛型类。现在让我们看看我们如何在应用程序中使用此库。

消费图书馆

该应用程序将存在通常的跨平台移动应用程序设置,这意味着我们将拥有涵盖Windows,Android和iOS的常规嫌疑人,其中包含便携式库库核心来共享可重用代码。

NativePclprojectoverview.

在核心我们拥有我们的业务逻辑代码和查看模型(我是MVVM Light库的巨大粉丝,了解更多查看我的 MVVM灯柱)。在NativePcl.core项目中我们有服务 osversionservice.cs. 返回版本号:

public class OsVersionService : IOsVersionService
{
    public string GetVersion()
    {
        return SystemInformationHandler.OSVersion;
    }
}

引用Osversion.Core库作为二进制文件 - 不要将其引用为项目,或者您将面临下一个步骤中的编译错误。不要问我怎么知道 眨眼微笑

因为Osversion库的所有组件都将被编译为具有相同名称的汇编,我们不能只是简单地引用项目文件,而是必须添加二进制I.E.库的编译版本。如果您正在从GitHub上查看样本,请确保在“osversion”在项目的发布输出文件夹中引用OsVersion,请在发布版本下编译oders构建。

该方法调用 osversion. Osversion库中的财产 - 留出特定项目。 UWP在这里完全意向。在客户端上,例如Android应用程序我们有一个单个屏幕,显示在中定义的版本号 mainview.xaml.:

<Page
    x:Class="nativepcl.uwp..MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:NativePcl.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="{Binding OSVersion}" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TitleTextBlockStyle}"></TextBlock>
    </Grid>
</Page>

以及我们使用的相应代码或使用视图模型 MainViewModel.cs.:

public class MainViewModel : ViewModelBase
{
    private readonly IOsVersionService _osVersionService;

    public MainViewModel(IOsVersionService osVersionService)
    {
        if (osVersionService == null) throw new ArgumentNullException(nameof(osVersionService));
        _osVersionService = osVersionService;
    }

    public string OSVersion => _osVersionService.GetVersion();
}

如果我们现在运行该应用程序,我们将获得以下输出:

核心转换

现在这是我们定义的输出 Osversion.Core.,如果我们现在引用二进制文件 Osversion.uwp. 在里面 nativepcl.uwp. 项目事情变得非常有趣。而不是收到错误,因为我们正在添加两个具有相同名称的组件,编译器将在PCL实现中更喜欢平台特定于平台库。即使我们从未直接从我们的图书馆举行 nativepcl.uwp. 应用程序现在返回的操作系统版本是从特定于平台返回的i.e. Osversion.uwp. 实施 getVersion() 方法导致以下输出:

UWPVersion.

虽然这种方法允许在PCL中编写平台独立逻辑,并且在运行时在运行时调用平台的实现,但它有点繁琐,因为它要求开发人员将引用库的正确版本。所有这些都有相同的名称,它只是呼唤一些沮丧的分钟,因为引用了错误版本的库而发生。幸运的是,存在一种技术,允许使用上述方法而不会使开发人员能够正确地引用二进制文件。 通过将图书馆包装在尼古特包中 消耗库与将包添加到所有项目中,并且尼古特包管理器就像构建引擎更喜欢将特定于PCL库的平台与项目联系起来。因此,不必选择其中的二进制文件添加开发人员现在只需将相同的NuGet包添加到所有项目即可工作。

结论

在此帖子中,您了解如何创建可以在PCL中消耗的API,并仍提供平台特定功能。对于所有这些工作,我们必须将项目的命名空间和装配设置为相同的名称。在消费者上,可以简单地添加包含所有实现的Nuget包,其中PCL,UWP,Android和IOS或将相应API编译的二进制文件添加到应用程序实现。 Osversion.Core.nativepcl.core..

此方法允许您创建API,该API可以在多个平台中重复使用,这些平台在平台上提供相同的方法定义。

您可以找到样品 GitHub.。 (确保首先作为版本构建编译)

Updated: