解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
16.95 KiB
X
# NewLife 移动端技术架构 > 版本:v4 | 数据截止:2026-10-17 > 关联:`Samples/Mobile.Core/`(共享冒烟与采集)、`Samples/Mobile.Console/`、`Samples/Mobile.Android/`、`Samples/Mobile.iOS/`、`.github/workflows/mobile.yml` ## 结论 1. **分层看问题**:运行时/平台绑定 → 基础库 → UI 框架 → 应用架构。跨层比较没有意义。 2. **Xamarin 已结束**:Xamarin.Android/iOS/Forms 于 2024-05-01 全部 EOL。新项目不再使用;旧项目按 UI 层迁移到 MAUI,或按平台层迁移到 .NET for Android/iOS。 3. **MAUI 是 .NET 移动 UI 的事实主栈**:跨平台 UI 包下载量约为 Avalonia 移动包的 36 倍、Uno 的 2.3 倍,适合表单/CRUD/内部工具。 4. **原生 .NET UI 是第二条路径**:设备能力重、性能敏感、薄封装原生 SDK 以及类库验证,优先原生薄壳。 5. **NewLife.Core 是基础库**:移动端兼容性只取决于 .NET for Android/iOS,与 UI 框架选型无关。 ## 1. 技术栈分层 | 层 | 作用 | 代表技术 | |---|---|---| | 运行时/平台绑定 | 让 C# 跑在 Android/iOS 上,暴露平台 API | .NET for Android / .NET for iOS | | 基础库 | 日志、配置、网络、序列化、缓存等 | BCL、NewLife.Core、NewLife.XCode | | UI 框架 | 界面、交互、导航 | 原生 .NET UI、.NET MAUI、Avalonia、Uno、Blazor Hybrid | | 应用架构 | MVVM、Shell、DI、模块化 | CommunityToolkit.Mvvm、MAUI Shell、Prism 等 | ```text Android / iOS └─ .NET for Android / .NET for iOS ← 运行时 + 平台绑定 ├─ BCL + NewLife.Core ← 基础库 └─ UI 框架 ├─ 原生 .NET UI(Android Views / UIKit) ├─ .NET MAUI ├─ Avalonia ├─ Uno Platform └─ Blazor Hybrid ``` MAUI、Avalonia、Uno、Blazor Hybrid 最终都跑在 .NET for Android/iOS 上;它们竞争的是 **UI 层**,不是运行时。 ## 2. UI 框架对比 | 方案 | 定位 | 优点 | 风险/限制 | 适用场景 | |---|---|---|---|---| | **.NET MAUI** | 官方跨平台 XAML/C# | 单项目覆盖 Android/iOS/桌面;MVVM、Shell、DI、热重载;生态最大 | 跨平台抽象有包体/启动/内存开销;复杂 UI 仍要平台代码;iOS 需要 Mac | 业务 App、表单/CRUD、内部工具 | | **原生 .NET UI** | C# 直接调用 Android/iOS API | 平台 API 全覆盖;启动、包体、性能最接近原生;最适合类库验证 | Android/iOS 两套 UI;平台知识要求高 | 设备能力重、性能敏感、原生 SDK 封装、Core 冒烟 | | **Avalonia** | 跨平台 XAML + Skia | 桌面成熟;自绘、自定义能力强 | 移动端成熟度和生态弱于 MAUI;包体/启动成本 | 桌面为主、顺带移动 | | **Uno Platform** | WinUI XAML 跨平台 | 复用 WinUI/UWP 技能;覆盖多端 | 复杂度和学习曲线高;移动性能/包体不占优;社区小 | WinUI/UWP 企业存量迁移 | | **Blazor Hybrid** | MAUI 宿主 + WebView + Razor | 复用 Web/Blazor 技能;表单型工具开发快;可调用原生能力 | WebView 性能、内存、滚动手感不如原生;复杂动画/手势不理想 | Web 团队、表单型内部应用 | | **PWA / Blazor Web** | 可安装的 Web App | 一套代码多端;更新即时;不需要 Mac 和应用商店 | 设备 API 受限;离线能力有限;iOS 限制更多 | Cube 管理后台、CRUD、内容管理 | | **Xamarin.Forms** | 旧跨平台 UI | — | 已 EOL,仅遗留维护 | 不用于新项目 | 补充说明: - **MAUI**:.NET 10 官方支持至 2027-05-11(MAUI 9 已于 2026-05-12 结束支持);最低 Android 5.0(API 21)/ iOS 12.2,Blazor Hybrid 为 Android 7.0(API 24)/ iOS 16.4。 - **原生 .NET UI**:没有 UI 框架干扰,问题能直接定位到 Core 或平台本身,是类库移动端验证的首选。 - **Avalonia**:GitHub 关注度高,但移动包下载量(Android 45.6 万 + iOS 29 万)远小于 MAUI,主要采用仍在桌面。 - **Uno**:WinUI 存量迁移有价值,但社区规模小(约 1.0 万 stars、402 个 Stack Overflow 问题)。 - **Blazor Hybrid**:Razor 组件在 .NET 进程中运行,不是浏览器 WebAssembly;仍依赖 MAUI 和 Mac 构建 iOS。 - **PWA**:蓝牙、NFC、后台定位、部分推送、文件系统等能力受限,不适合设备密集型应用。 ## 3. 采用度(代理指标) | 技术 | NuGet 总下载 | Stack Overflow 标签 | GitHub stars | 备注 | |---|---:|---:|---:|---| | .NET MAUI | Microsoft.Maui.Controls 26,737,363 | maui 8,679 | 23,322 | 官方跨平台 UI | | Avalonia | Android 455,608;iOS 290,022;桌面 24,169,947 | avaloniaui 596 | 31,664 | 桌面强,移动包小 | | Uno Platform | Uno.WinUI 11,552,527 | uno-platform 402 | 10,080 | 含桌面/Web/移动 | | Xamarin.Forms | 86,235,061 | xamarin.forms 34,573 | — | 历史累计,已 EOL | | MAUI 生态 | CommunityToolkit.Maui 10,056,783 | — | — | MAUI 活跃度 | 口径:NuGet 是累计下载(含 CI 和重复还原),Stack Overflow 是累计问题量,GitHub stars 是关注度;只能看相对量级,不是精确市占率。 ## 4. 选型决策树 ```text 是否必须做成原生 App? ├─ 否 → PWA / 响应式 Web / Blazor Web(Cube 后台、CRUD、内部系统) └─ 是 ├─ UI 以表单/CRUD/内部工具为主? → .NET MAUI(默认候选) ├─ 设备能力重/性能敏感/需要薄封装原生 SDK? → 原生 .NET UI ├─ 桌面优先、顺带移动? → Avalonia ├─ WinUI/UWP 企业存量? → Uno Platform ├─ 团队以 Web/Blazor 为主? → Blazor Hybrid(MAUI 宿主) └─ 已有 Xamarin? → 迁移 .NET MAUI(Forms)或原生 .NET ``` 约束: - **iOS 构建**:以上所有 .NET UI 方案都需要 macOS;没有 Mac 时优先 macOS CI。 - **真机**:iOS 真机还需要 Apple 账号/签名;模拟器不需要。 - **不要只看下载量/Stars**:份额高不等于适合你的团队和场景;POC 验证性能、包体、设备能力和维护成本更重要。 ## 5. 对 NewLife 的建议 ### 5.1 NewLife.Core 的移动端验证 - **用原生 Android/iOS 薄壳 + 共享冒烟库**,不绑定 MAUI/Avalonia/Uno; - 目的:验证 Core 的 `net10.0` 资产在 Mono/AOT/裁剪下的行为,而不是验证某个 UI 框架; - 用例覆盖:平台信息、日志、配置、缓存、定时器、JSON/二进制序列化、TCP/HTTP/WebSocket 回环、安全加密、归档、对象容器、动态能力降级; - Android:真机验收 + API 36 模拟器回归;iOS:GitHub Actions `macos-26` 模拟器; - Release + 裁剪/AOT 作为门禁;Debug 只用于快速定位; - 真机排查用 `Samples/Mobile.Android`:屏幕即控制台,可查看 `MachineInfo` 与 Android 原生信息。 **TFM 策略:不增设移动目标框架** - 兼容方向是单向的:`net10.0-android` / `net10.0-ios` App 可以引用 `net10.0` 资产,反之不行。Android/iOS 冒烟工程还原时,`NewLife.Core` 的目标框架就是 `.NETCoreApp,Version=v10.0`(见各自 `obj/project.assets.json`)。 - 因此 Core 维持现有输出,不增加 `net10.0-android` / `net10.0-ios`:库内没有平台专有 API,Windows 专有代码由 `WINDOWS`/`NETFRAMEWORK` 隔离,平台差异用运行时判断。 - 增设的代价:android/ios workload 成为全仓构建前置;多两份 IL/XML;移动端会优先选择平台资产,`SupportedOSPlatformVersion` 或行为分叉会变成移动专属故障。 - 实测构建行为:给 Core 加移动 TFM 后,没有对应 .NET workload 的机器执行 `dotnet build -f net10.0` 仍会因其它 TFM 报 `NETSDK1208`;以 ProjectReference 引用 Core 的工程同样失败。`-p:TargetFrameworks=net10.0` 可绕过;只消费 nupkg 的 `net10.0` 工程不受影响(自动选 `lib/net10.0`)。 - 只有以下情况才重新评估:Core 自身要直接调用 Android/iOS 平台 API、需要平台原生资产,或必须按平台编译不同实现。 - 平台信息采集不依赖 TFM:Android 内存读 `/proc/meminfo`,iOS 用 `sysctl`;`android_id` 等平台专属字段优先走 `IMachineInfo` 扩展或独立平台包。 **移动端日志:不新增 UseXxx** - 文件日志用 `TextFileLog`,Android/iOS 均可用,路径取应用数据目录; - UI 或 logcat/NSLog 由宿主实现一个 `Logger` 子类(或 `ActionLog`),再用 `CompositeLog` 组合文件日志;`Samples/Mobile.Android/MainActivity.cs` 的 `TextViewLog` 是现成示例; - Core 不新增 `UseAndroid` / `UseiOS`:UI sink 绑定 Activity/UIViewController,平台 API 依赖会把 workload 引入主库;需要开箱即用时做可选 `NewLife.Core.Android` / `NewLife.Core.iOS` 包; - `UseConsole` 适合控制台,`UseWinForm` 是 Windows 专用,均不适用于移动端。 **星尘接入(可选)** - 默认构建不引用 `NewLife.Stardust`,保持“只访问 127.0.0.1 + Release 全裁剪/AOT”的冒烟门禁; - `Samples/Mobile.Stardust.Core` 在 `IncludeStardust=true` 时提供可选接入(`MobileAgent` / `MobileStarClient` + `CoreMobilePlatform`),设备信息复用 `MachineInfo`; - Android:`run-android.ps1 -Mode Aot -Stardust`;iOS:`INCLUDE_STARDUST=true run-ios.sh`; - Stardust 构建使用 partial 裁剪并保持 AOT,避免 Android 10 真机 JIT 冷启动崩溃;服务端默认 `http://star.newlifex.com:6600`,产品编码 `StarAgent-Mobile`。 已知限制(截至本次真机验证): - Android 的 `MachineInfo` 已补齐系统、硬件、内存与 `android_id`;iOS 由 `MachineInfo.iOS.cs` 用 `sysctl` 补齐系统名称、系统产品版本、设备型号与内存,宿主 `IOSMachineInfoProvider` 补充设备名称、稳定标识与电池。温度按平台能力由宿主 `IMachineInfo` 补充;Android 宿主还会补充厂商市场名称(`ro.product.marketname`)、系统设备名称与可读序列号。Android 10+ 普通应用无法读取 IMEI/MEID,序列号通常也不可读,此时硬件唯一标识继续使用 `android_id`; - iOS 模拟器上的 `hw.machine` / `hw.model` / `kern.osproductversion` 可能反映宿主环境,真机才是设备标识; - `ProcessHelper` 在受限平台可能抛 `PlatformNotSupportedException`,冒烟用例标记 SKIP; - `PluginHelper` 动态加载在 AOT 下按设计不支持,冒烟用例验证其抛出明确异常。 ### 5.2 未来 NewLife 移动 App - **业务 App 默认候选 MAUI**:表单/CRUD/内部工具/多端覆盖,C# 团队效率最高; - **设备密集型下沉原生**:BLE、相机、传感器、后台服务、音视频、性能敏感场景; - **Cube 管理后台优先 PWA/响应式 Web**:移动端访问管理后台通常不需要原生 App; - **Avalonia/Uno 只在特定约束下选**:桌面优先或 WinUI 企业存量,不作为 NewLife 业务 App 的默认; - **Blazor Hybrid 适合 Web 团队**:已有 Blazor 组件库时收益最大。 ### 5.3 iOS 构建策略 - 没有 Mac:用 GitHub Actions `macos-26`(已确认 Xcode 26.6 + .NET 10.0.400)跑模拟器; - 有 Mac:本地模拟器 + 真机调试; - 真机分发需要 Apple 开发者账号/签名;库级验证用模拟器即可; - 不要因为“Windows 能编译 iOS 类库”就误以为能在 Windows 运行 iOS App。 ## 6. 示例工程与输出 移动端示例已合并为一组平铺项目,不再有 `Samples/MobileSmoke` / `Samples/MobileConsole` 两个入口: | 项目 | 职责 | 输出目录 | |---|---|---| | `Samples/Mobile.Core` | `MachineInfoReport` + 21 个冒烟用例 | `Bin\Mobile.Core` | | `Samples/Mobile.Console` | 桌面宿主,默认系统信息,`--smoke` / `--all` | `Bin\Mobile.Console` | | `Samples/Mobile.Android` | 原生 Activity 控制台,系统信息 + 冒烟 + XTrace | `Bin\Mobile.Android` | | `Samples/Mobile.iOS` | 原生 UIViewController,系统信息 + 冒烟 | `Bin\Mobile.iOS` | Android 安装包统一为 `com.newlife.mobile`,桌面显示名为“新生命测试台”,首页标题为“新生命移动测试台”;主 README 在 `Samples/Mobile.Android/README.md`。仓库根目录的 `AotSmoke` 是 Windows/Linux 的 NativeAOT 冒烟,不是移动端 App,也不参与 APK 打包。 ## 7. 构建、打包与分发 ### 7.1 命令与产物 ```powershell # 桌面:系统信息 / 冒烟 / 两者 dotnet run --project Samples/Mobile.Console -c Release dotnet run --project Samples/Mobile.Console -c Release -- --smoke dotnet run --project Samples/Mobile.Console -c Release -- --all # Android:JIT / Mono AOT / NativeAOT(实验性) pwsh Samples/Mobile.Android/pack-android.ps1 -Mode Jit pwsh Samples/Mobile.Android/pack-android.ps1 -Mode Aot pwsh Samples/Mobile.Android/pack-android.ps1 -Mode NativeAot ``` `dotnet build` 和 `dotnet publish` 都可以产出 Android APK;本项目统一用 `pack-android.ps1` 封装: - 构建中间产物在 `Bin\Mobile.Android\android-arm64`; - 最终 APK 复制到 `Bin\Mobile.Android\apk\Mobile-<Mode>.apk`; - 脚本输出 APK 绝对路径、大小和 SHA256。 ### 7.2 APK 结构与分发 - Android APK 同时包含 `arm64-v8a` 和 `x86_64`,真机和模拟器均可安装。 - AOT APK 内含 Mono 运行时(`libmonosgen-2.0.so`)和 AOT 后的程序集(`libaot-*.dll.so`);JIT APK 只有 IL 程序集。 - `-Signed.apk` 使用本机自动生成的 debug keystore 签名,可拷贝到其他手机侧载安装: ```powershell adb install -r Bin\Mobile.Android\apk\Mobile-Aot.apk ``` - debug 签名只适合内部测试;正式分发需配置 release keystore: ```powershell dotnet publish Samples/Mobile.Android/Mobile.Android.csproj -c Release -f net10.0-android ` -p:RuntimeIdentifier=android-arm64 ` -p:AndroidKeyStore=true ` -p:AndroidSigningKeyStore=<keystore> ` -p:AndroidSigningKeyAlias=<alias> ` -p:AndroidSigningKeyPass=<keypass> ` -p:AndroidSigningStorePass=<storepass> ``` - 不同开发机的 debug keystore 不同;跨机升级需卸载重装,或统一使用同一 release keystore。 ## 8. 运行时与 AOT ### 8.1 三种打包模式 | 模式 | 构建方式 | 运行时 | 实测大小 | 特点 | |---|---|---|---:|---| | `Jit` | Release + `RunAOTCompilation=false` | Mono JIT | 9.40 MB | 构建最快、调试方便;启动和 JIT 开销较大 | | `Aot` | Release 默认 | Mono AOT(normal + profiled) | 12.47 MB | 默认交付;启动更快;包体更大;反射基本可用 | | `NativeAot` | `PublishAot=true` + `UseMonoRuntime=false` | NativeAOT | 15.40 MB | 已实测可构建(实验性);需 Android NDK 26.3(脚本自动定位 clang/LLVM);API 36 x86_64 模拟器冒烟 21/21 通过;反射、动态加载、裁剪约束最多;未真机验证 | > 以上三种都是同一个 Android 项目的不同运行时/编译配置,**都可以产出 APK**;NativeAOT 仍会给出 XA1040 实验性警告,不应当作默认交付。本机已用 NDK 26.3.11579264 完成 NativeAOT 构建(APK 15.40 MB,内含 `lib/arm64-v8a` 与 `lib/x86_64` 原生库),并在 API 36 x86_64 模拟器跑通共享冒烟 21/21;`pack-android.ps1` 会自动定位 NDK 并把 `clang`/LLVM 加入 PATH。真机运行验证待补。 ### 8.2 为什么 Release 默认是 Mono AOT 已安装的 `Microsoft.Android.Sdk.Windows/36.1.118` 默认属性: ```text RunAOTCompilation = true # Release + MonoVM AndroidEnableProfiledAot = true AndroidAotMode = Normal UseMonoRuntime = true ``` Debug 默认 `RunAOTCompilation=false`,即 Mono JIT。因此: - **Debug APK**:JIT,构建快,适合调试; - **Release APK(默认)**:Mono AOT,当前手机上的安装包就是这一形态; - **NativeAOT APK**:需要显式 `PublishAot=true`,本机缺 clang/NDK 时会在链接阶段失败。 ### 8.3 选型建议 - 日常开发、断点调试:`Jit` / Debug; - 真机验收、CI 门禁、侧载分发:`Aot`(默认); - 需要极致启动/内存且能接受反射限制:再评估 `NativeAOT`; - `UseMonoRuntime=false` 还可选择 CoreCLR 运行时,但本项目未作为默认交付;需要单独验证启动、包体和反射行为。 ## 9. 参考资料 > 抓取日期:2026-10-17。 - NuGet Search API:`https://azuresearch-usnc.nuget.org/query` - Stack Exchange API:`https://api.stackexchange.com/2.3/tags/{tag}/info?site=stackoverflow` - GitHub REST API:`https://api.github.com/repos/{owner}/{repo}` - .NET MAUI 支持平台:`https://learn.microsoft.com/dotnet/maui/supported-platforms` - .NET MAUI 支持周期:`https://dotnet.microsoft.com/platform/support/policy/maui` - Xamarin 结束支持:`https://dotnet.microsoft.com/platform/support/policy/xamarin` - .NET for Android:`https://learn.microsoft.com/dotnet/android/` - .NET for iOS:`https://learn.microsoft.com/dotnet/ios/` - .NET NativeAOT 部署:`https://learn.microsoft.com/dotnet/core/deploying/native-aot/` - Blazor Hybrid:`https://learn.microsoft.com/aspnet/core/blazor/hybrid/` - Avalonia Android:`https://docs.avaloniaui.net/docs/platform-specific-guides/android` - Avalonia iOS:`https://docs.avaloniaui.net/docs/platform-specific-guides/ios` - GitHub Actions macOS 26 镜像:`https://github.com/actions/runner-images` - Android Emulator Runner:`https://github.com/ReactiveCircus/android-emulator-runner`