maui-cn

基于.NET的跨平台应用程序框架介绍

随着.NET 8的发布,我也将我的书.NET MAUI Cross-Platform Application Development更新到了第二版,已经在3月25日开始正式发行。第一版是基于.NET 6编写的,第二版更新到了 .NET 8。这是一本介绍.NET MAUI的书籍。可以通过下面的链接购买。

https://epa.ms/maui

figure00

在第二版的评审过程中,通过与同行的交流,我总觉得并不应该只用.NET MAUI来代表基于.NET的跨平台解决方案。

.NET MAUI是一种跨平台应用框架,在这里我强调的是应用框架。它与其它的主流跨平台应用框架如Flutter,React Native或者Ionic等一样,都属于应用框架。应用框架通常是建立在通用框架和相应的编程语言之上的。我们有很多通用框架和语言可选择,如Java/JVM,JavaScript/Node.js以及C#/.NET Core等。跨平台应用开发的挑战主要来自于对用户界面的处理,所以根据不同的用户界面处理方案,我们大致可以将跨平台应用框架分为以下三类。

  • 原生用户界面抽象化:通过抽象化用户界面元素,将其映射到系统的原生控件。目前.NET MAUI和React Native使用这种方案。这种方案的好处是,应用的用户界面与原生是一致的。原生控件的更新变化,会自动在应用中生效。缺点是比较难将控件精确的映射到每个所支持的平台。
  • 使用2D图形库:使用2D图形库来绘制用户界面控件。Flutter和Avalonia UI使用的是这种方案。好处是摆脱了对原生控件的依赖。对所有支持的平台,应用界面高度一致。缺点是与原生控件的行为可能不一致,特别是原生控件更新了以后,跨平台应用的行为会与原生控件有差异。
  • 使用WebView:这一方案是通过使用浏览器的界面来构建用户界面。Ionic和.NET MAUI Blazor都使用这种方案。这种方案可以重用前端应用的代码,因为都是以HMTL/CSS/JavaScript来构建的。但这个方案会受到基于浏览器的局限,用户界面更类似网页应用而非原生应用。

从上面的分类可以看出,基于.NET的应用框架,涵盖了所有可能的实现方式,而非只是基于.NET MAUI的跨平台方案。本文将对基于.NET的应用框架做一个介绍和初步的比较。

基于.NET的跨平台应用框架主要有下面几种:

  • .NET MAUI
  • .NET MAUI Blazor Hybrid
  • Avalonia UI
  • Uno Platform
  • Xamarin (.NET for Android, .NET for iOS and .NET for Mac)

这些应用框架都是建立在.NET之上的,或者说是建立在.NET 6之后的.NET之上的。因为原始的.NET Framework本身并不是一个跨平台框架。通过与开源项目Mono的整合,才逐渐演变成了今天的类似Java/JVM的跨平台通用框架。开源项目Mono提供了对Android, iOS, macOS和Linux等的.NET支持。Mono项目的另一重要贡献就是开发了Xamarin这一层中间件。我之所以使用中间件而非框架来描述Xamarin,是因为它本身并不是一个全新的东西,它只是为其下的平台提供.NET接口。通过使用Xamarin,.NET应用可以直接使用C#访问几乎所有平台提供的功能。如,Xamarin.Android提供了所有原生的Android API。同样的Xamarin.iOS也提供了所有iOS的API。

在Xamarin的基础上,开源团队推出了Xamarin.Forms这一跨平台用户界面解决方案。Xamarin提供了使用.NET/C#进行原生开发的能力。非用户界面代码封装成.NET Standard库来实现代码复用。
如下图所示的Xamarin.Forms架构图。

figure01

Figure 1: Xamarin.Forms 架构

在上图中,我用上标标出了相应开源代码的链接。你可以参考本文底部的参考链接。基于Xamarin的方案有多种实施方式。

Xamarin.Forms和.NET MAUI的跨平台方案都是通过抽象原生控件来实现的。抽象化的控件通过Xamarin.Forms renderer或者.NET MAUI handlers映射到原生控件上,如下图所示。

figure02

Figure 2: Xamarin.Forms Renderers and .NET MAUI Handlers

在上图中,可以看到抽象控件Button在Xamarin.Forms和.NET MAUI中的实现。在Xamarin.Forms中,跨平台控件Button,通过ButtonRenderer映射到不同平台的原生控件,如在iOS上的UIButton,Android上的AppCompatButton和Windows上的 Button。
在.NET MAUI中,跨平台控件Button,通过IButton接口和ButtonHandler映射到不同平台的原生控件。

如果想最大限度地复用代码,你可以使用Xamarin.Forms和.NET Standard库,这样代码的复用率可以达到90%以上。

如果你对性能和用户体验有较高的要求,可以直接基于Xamarin构建应用,这种开发非常类似于原生开发。所有的平台都使用.NET和C#,在一定程度上也可以复用代码。

figure03

Figure 3: Native Application Development using Xamarin

微软在.NET 6之后发布了.NET MAUI。可以说,.NET MAUI比起Xamarin.Forms更像是一种演进,而不是革命性的变化。如下图所示,.NET MAUI取代了Xamarin.Forms。而.NET for Android,.NET for iOS和.NET for Mac也无疑都是Xamarin.Android,Xamarin.iOS和Xamarin.Mac的更新。为了方便起见,在本文中,我仍然将使用Xamarin表示此层。几个基于Xamarin项目的GitHub仓库仍然是一样的。.NET本身自.NET 5以来,也出现了很大的变化,也就是在所有平台上都有了统一的.NET BCL。

figure04

Figure 4: .NET MAUI 架构

在发布.NET MAUI之后,我们仍然可以使用Xamarin进行原生开发,并不一定非得使用.NET MAUI。例如,我们可以单独使用.NET for Android来使用.NET/C#来开发原生Android应用。

.NET MAUI还有一种使用方式,即使用Blazor开发.NET MAUI Blazor Hybrid应用。Blazor是一种基于.NET的网络应用开发方案。在.NET MAUI中,增加了一个特殊的控件BlazorWebView。这是一个支持Blazor的WebView控件。我们可以使用BlazorWebView来开发用户界面,这样我们就可以使用同一套代码来开发网络、移动以及桌面应用。

使用.NET MAUI开发跨平台应用,目前并不支持Linux。虽然有开源项目在开发Linux的支持,但进展并不顺利。.NET MAUI借助将抽象控件映射到原生控件的方案,在Linux上比较困难。Linux与Android,iOS,macOS,Windows等不同,没有统一的用户界面库,而是具有多个用户界面库如GTK或QT等。

在基于.NET的方案中,Avalonia UI和Uno Platform都支持Linux。下面我们将分别介绍这两者。

Avalonia UI使用2D图形库自行实现控件。如下图所示,除了2D图形库Skia,Avalonia UI只依赖于.NET。在.NET之上,Avalonia UI使用Skia库实现了自己的所有控件。因此,Avalonia UI在所有平台上的表现非常一致。

figure05

Figure 5: Avalonia UI 架构

Avalonia UI这个开源项目起源于将WPF框架扩展到macOS和Linux的想法,它起初是一个桌面应用框架。而在.NET 6之后,该项目也把移动应用和WebAssembly加入了框架之中。基于Avalonia UI的应用编程与WPF应用的开发过程高度类似。对于熟悉WPF应用开发的开发者来说,这是非常容易上手的。

除了.NET MAUI和Avalonia UI外,我们还要比较的另一个跨平台框架是Uno Platform。.NET MAUI和Avalonia UI都非常具有代表性,分别代表了使用原生控件和使用2D图形库的跨平台实现。而Uno Platform则是一个兼具两种特性的解决方案,如下图所示。

figure06

Figure 6: Uno Platform 架构

Uno Platform针对不同的系统采用了不同的解决方案。

  • Android、iOS和macOS:Uno Platform使用了Xamarin来实现在Android,iOS和macOS上的控件。这点与.NET MAUI类似,但由于Uno Platform也是从WPF演变来的,因此Uno应用的编写方式也与WPF类似。在最新的版本中,直接使用了WinUI 3。
  • Windows:如果是Windows应用,在Uno Platform上,与WinUI 3的应用没有任何区别。
  • Linux:对Linux的支持方面,Uno Platform使用了与Avalonia UI相同的方式,即通过Skia自行实现控件。
  • WebAssembly:对WebAssembly的支持则是将C#/XAML转换成HTML/CSS。

从这里我们可以看出,Uno Platform采用的是一种混合的实现方式。

下面的表格对这几种跨平台方案进行了总结和比较。

table01

当我们将所有框架组合在一起时,我们可以看到下面的图7。尽管看上去有点复杂,但这个图清楚地展示了.NET MAUI、Uno平台和Avalonia UI如何融入.NET架构。

figure07

Figure 7: .NET cross-platform solutions

通过本文的介绍,我们可以看到,基于.NET的跨平台方案有多种实现方式,每种实现方式都有其优缺点。选择哪种方案需要根据实际的使用场景来决定。

References:

  1. .NET MAUI source code
    https://github.com/dotnet/maui
  2. .NET for Android source code – Both .NET for Android and Xamarin.Android are built from this repository with different build configurations.
    https://github.com/xamarin/xamarin-android
  3. .NET for iOS source code – Both .NET for iOS and Xamarin.iOS are built from this repository with different build configurations.
    https://github.com/xamarin/xamarin-macios
  4. .NET for Mac source code - .NET for iOS and .NET for Mac are shared the same code base with different build configuration.
    https://github.com/xamarin/xamarin-macios
  5. WinUI
    https://github.com/microsoft/microsoft-ui-xaml
  6. Avalonia UI
    https://github.com/AvaloniaUI/Avalonia
  7. Skia
    https://github.com/google/skia
  8. Uno Platform
    https://github.com/unoplatform/uno
  9. Avalonia UI and MAUI - Something for everyone
    https://www.avaloniaui.net/Blog/avalonia-ui-and-maui-something-for-everyone
  10. Xamarin.Forms
    https://github.com/xamarin/Xamarin.Forms
  11. Mono
    https://github.com/mono/mono
  12. .NET MAUI Cross-Platform Application Development
    https://www.packtpub.com/product/net-maui-cross-platform-application-development-second-edition/9781835080597

摘要

该文章对.NET跨平台应用程序框架进行了深入的评述。它介绍了.NET跨平台应用程序框架,并将其与其他应用程序框架(如Flutter、React Native或Ionic)进行了比较。文章还介绍了基于.NET的各种可用的跨平台应用程序框架,包括.NET MAUI、.NET MAUI Blazor混合、Avalonia UI、Uno平台和Xamarin。 此外,它解释了这些框架的使用和好处以及它们的比较,包括它们的架构。它得出的结论是,框架的选择在很大程度上取决于实际使用场景,因为所有框架都有其独特的优点和缺点。