可以考虑编写自适应代码,这与创建自适应 UI 的方式类似。 将基本代码设计为在最低操作系统版本上运行,然后在检测到应用在有新功能的更高版本上运行时添加功能。
有关 ApiInformation、API 协定以及如何配置 Visual Studio 的背景信息,请参阅版本自适应应用。
先决条件
- Windows 应用 SDK项目(打包或解压缩)。 请参阅 快速入门:创建第一个 WinUI 3 应用。
- 熟悉 Windows 运行时(WinRT)类型系统,因为
ApiInformation检查仅适用于Windows.*命名空间中的类型。
运行时 API 检查
在代码中的条件语句里使用 Windows.Foundation.Metadata.ApiInformation 类,以测试要调用的 API 是否存在。 无论你的应用在何处运行,都会对该条件进行求值,但只有在设备上提供了该 API 且可调用时,其结果才会是 true。
Important
ApiInformation 检查仅适用于 Windows.* 命名空间中的 Windows 运行时 类型。 它们无法检测 WinUI 类型(Microsoft.UI.Xaml.*),因为这些类型属于 Windows 应用 SDK 框架包,而不是操作系统,并且也没有注册为 ApiInformation 可查询的 WinRT 元数据。
#if 预处理器指令也无济于事—它们基于目标框架在编译时评估,而不是基于应用实际运行的 OS 或 SDK 版本在运行时评估。 若要有条件地启用 WinUI 功能,请检查应用所针对的 Windows 应用 SDK 版本(请参阅 版本自适应应用),或者将该调用包装在 try/catch 中,并在其于运行时失败时回退到备用方案。
Tip
许多运行时 API 检查可能会影响应用的性能。 执行一次检查并缓存结果,然后在整个应用中使用缓存的结果。
自适应代码选项
可通过两种方法创建自适应代码:
- 应用代码 — 在代码后置文件中使用运行时 API 检查。 对于大多数方案,建议使用此方法。
- 状态触发器 - 使用可扩展状态触发器,根据 API 的存在激活视觉状态。 当不同 OS 版本之间仅存在与某个视觉状态相关联的简单属性或枚举值变化时,请使用状态触发器。
示例:检查枚举值
此示例演示如何在使用某个特定枚举值之前,先检查该值是否存在。 如果该值不存在,代码将回退为备选值。
EnergySaverStatus 和 PowerManager 是 Windows.System.Power 命名空间中真正的 Windows 运行时 类型,因此 ApiInformation 可以正确查询它们。
if (ApiInformation.IsEnumNamedValuePresent(
"Windows.System.Power.EnergySaverStatus", "On"))
{
if (PowerManager.EnergySaverStatus == EnergySaverStatus.On)
{
// Reduce background work to save battery.
ReduceBackgroundActivity();
}
}
else
{
// Energy Saver status isn't available on this OS version; skip the check.
}
void ReduceBackgroundActivity()
{
// Pause non-essential timers, syncs, and animations here.
}
Important
缓存 API 检查的结果时,请在整个应用中一致地使用该缓存值。 不要在多个位置重复检查 - 检查一次,存储结果,并在任何地方引用它。
示例:检查某个方法是否存在
用于 IsMethodPresent 在调用特定方法之前验证特定方法是否可用:
DisplayRequest displayRequest = new DisplayRequest();
if (ApiInformation.IsMethodPresent(
"Windows.System.Display.DisplayRequest", "RequestActive"))
{
displayRequest.RequestActive();
}
示例:检查某个属性是否存在
用于 IsPropertyPresent 在读取特定属性之前验证该属性是否可用:
if (ApiInformation.IsPropertyPresent(
"Windows.System.Power.PowerManager", "RemainingChargePercent"))
{
int chargePercent = PowerManager.RemainingChargePercent;
}
最佳做法
| 练习 | Guidance |
|---|---|
| 使用静态字符串 | 使用 ApiInformation 检查 API 名称时,应使用硬编码字符串而不是 .NET 反射,以避免运行时类型加载问题 |
| 缓存结果 | 在启动时执行每个 API 检查一次,并存储结果以供重复使用 |
| 尽量降低最低版本要求 | 将项目的最低版本设置为尽可能低,以达到最广泛的受众,并使用自适应代码在较新的 OS 版本上亮起功能 |
| 在最低版本上测试 | 始终在受支持的最低操作系统版本上进行测试,以验证回退路径是否正常工作 |