MAUI 入门教程系列(3.多目标平台)

前言

如果您是第一次创建MAUI项目, 并且在之前也并没有接触过Xamarin.Forms应用, 或许你并不知道MAUI的强大优势, 在原来的Xamarin.Forms当中, 我们基于不同平台的项目他们是单独维护的。.
如下所示:
MAUI 入门教程系列(3.多目标平台)

因为如此, 你需要维护不同平台的项目。包括每个项目当中包含的资源、图像、属性定义, Nuget包引用, 都需要保持一致。

在MAUI项目当中, 你不会再存在类似的问题, .NET MAUI 相比Xamarin.Forms 最大的区别就在于, MAUI是单个项目支持多个平台。MAUI 应用的项目包含 一个 Platform 文件夹,每个子文件夹都表示 .NET MAUI 可以面向的平台:
MAUI 入门教程系列(3.多目标平台)
每个文件夹代表了每个平台特定的代码, 在默认的情况下 编译阶段仅仅会编译当前选择的平台文件夹代码。

当你选择编译Windows平台的时候,Android、IOS等文件夹会忽略编译阶段,仅编译Windows平台相关代码, 同理其他平台也是一样。

这个时候, 我们可能就存在一个问题, 既然一个项目包含了这么多平台的代码, 那么它应该怎么区分哪些代码属于哪个平台?

这也正是MAUI项目默认通过文件夹来区分平台定义的方式, 那是不是还有别的方式来区分不同平台的代码?确实有的, 我们还可以通过文件名定义的方式来区分不同平台。

基于文件名的多目标

为了能够让VisualStudio 区分当前编译的平台中, 哪些代码应该被编译, 哪些代码应该被忽略, 所以我们通过文件的结尾命名来区分。在这里, 首先我们需要在项目中添加以下XML代码

        <ItemGroup Condition="$(TargetFramework.StartsWith('net6.0-android')) != true">
		<Compile Remove="**\**\*.Android.cs" />
		<None Include="**\**\*.Android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
	</ItemGroup>

	<ItemGroup Condition="$(TargetFramework.StartsWith('net6.0-ios')) != true AND $(TargetFramework.StartsWith('net6.0-maccatalyst')) != true">
		<Compile Remove="**\**\*.iOS.cs" />
		<None Include="**\**\*.iOS.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
	</ItemGroup>

	<ItemGroup Condition="$(TargetFramework.Contains('-windows')) != true ">
		<Compile Remove="**\*.Windows.cs" />
		<None Include="**\*.Windows.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
	</ItemGroup>

选择当前的项目, 右键编辑项目文件, 添加如上所示的代码即可。

该XML的主要作用是将生成系统配置为在特定条件下删除基于平台的文件名模式:

  • 不要编译文件名以 .Android 结尾的 C# 代码。cs,如果不为Android生成。

  • 不要编译文件名以 .iOS 结尾的 C# 代码。cs,如果未为 iOS 或 MacCatalyst 生成。

  • 不要编译文件名以 .Windows 结尾的 C# 代码。cs,如果不为Windows生成。

配置完成后, 我们就可以不必在Platform文件夹中去单独定义了, 我们随便编写一个Services文件夹, 添加基于不同平台的模拟代码。
MAUI 入门教程系列(3.多目标平台)

在实现的代码当中, 我们模拟在方法中创建基于不同平台的进度条控件。

    public interface ILocalService
    {
        void GetValue(string key);
    }
    
    //Android
    partial class LocalService : ILocalService
    {
        public void GetValue(string key)
        {
            new Android.Widget.ProgressBar(null);
        }
    }

    //IOS
    partial class LocalService : ILocalService
    {
	 public void GetValue(string key)
	 {
	   new UIKit.UIProgressView();
	 }
    }
   
   //Windows
   partial class LocalService : ILocalService
    {
        public void GetValue(string key)
        {
            new ProgressBar();
        }
    }

同时, 基于文件夹的多目标可以与基于文件名的多目标组合在一起。 

总结

这一节, 主要是介绍了MAUI当中的单项目支持多目标平台, 以及与传统的Xamarin.Forms的差异, 在下一节中, 则会介绍MAUI当中的依赖注入, 以及针对Xamarin.Forms的差异进行详细对比。