你的 App 类是共享的。每个平台只增加一个小文件,
它构造 App 并交给一个运行器。这就是一个典型应用的全部平台面
— 六个文件,没有一个长过一屏。
WindowsApp.Run 及其同族会创建窗口或表面,
拉起图形后端,用该平台的服务实现调用
DeviceServices.Initialize,最后调用 BaseApp.Init —
后者最终会调用你的 Create。你的代码从不
构造设备服务,也从不接触交换链。
| 命名空间 | 运行器 | 后端 |
|---|---|---|
Season.Platforms.Windows | WindowsApp.Run(BaseApp) | Direct3D 12 |
Season.Platforms.Linux | LinuxApp.Run(BaseApp) | Vulkan,基于 SDL |
Season.Platforms.Android | AndroidApp.Run(BaseApp) | Vulkan |
Season.Platforms.iOS | iOSApp.Run(BaseApp) | Metal |
Season.Platforms.MacCatalyst | MacCatalystApp.Run(BaseApp) | Metal |
Season.Platforms.Web | WebApp.Run(...),可等待 | WebGPU |
Windows — Platforms/Windows/App.xaml.cs
using Season.Platforms.Windows;
public partial class App : Microsoft.UI.Xaml.Application
{
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
WindowsApp.Run(new Hello.App());
}
}
Linux — Platforms/Linux/Linux.cs
using Season.Platforms.Linux;
internal class Program
{
static void Main(string[] args) => LinuxApp.Run(new App());
}
Android — Platforms/Android/MainActivity.cs
using Season.Platforms.Android;
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true,
ScreenOrientation = ScreenOrientation.FullSensor)]
internal class MainActivity : BaseActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
if (!AndroidApp.IsInitialized)
AndroidApp.Run(new App());
base.OnCreate(savedInstanceState);
}
}
派生自 BaseActivity 是把 Android 生命周期
和触摸事件接入引擎的方式。
AndroidApp.IsInitialized 守卫很重要,因为 Android
会重建 activity:一次配置变更绝不能启动第二个引擎。
iOS and Mac Catalyst — Platforms/iOS/Program.cs
using Season.Platforms.iOS;
internal class Program
{
static void Main(string[] args) => iOSApp.Run(new App());
}
Web — 在 Blazor WebAssembly 页面中,画布存在之后
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender || _started) return;
_started = true;
await WebApp.Run(new App(), JSRuntime, HttpClient, CanvasId, "");
}
WebApp.Run(BaseApp app, IJSRuntime jsRuntime, HttpClient
httpClient, string canvasId = "season-canvas", string? assetBasePath = null)。
IJSRuntime 是引擎访问 WebGPU 设备的途径,
而 WebGPU 设备存在于 JavaScript 中;HttpClient 是资产
加载的方式,因为浏览器没有同步文件系统。如果你的资产不是从
应用根路径提供的,就传入一个
assetBasePath。
偶尔你确实需要。DeviceServices.Core.Platform 返回
一个 Platform 值 —
Windows、Linux、
MacCatalyst、Android、
iOS 或 Web — 而
参考应用用它来把功能挡在无法承载它们的平台之外。
if (DeviceServices.Core.Platform is Platform.Web)
{
// No window capture, no local model inference.
}
// Services that are not implemented everywhere are null, not stubs.
if (DeviceServices.Recorder != null)
await DeviceServices.Recorder.Start();
null 检查是约定,而不是防御性习惯:在某个平台上没有实现的服务会被有意留为 null, 这样缺口在调用处就可见,而不是在运行时静默失败。完整列表见 跨平台支持。