AOT 支持

自.NET8,.NET团队在逐步做NativeAOT支持。

本框架支持这种发布方式:核心包、驱动包与部分扩展包都做了NativeAOT适配,并标注了 IsAotCompatible。

但NativeAOT并不是免费的午餐。你要做提前编译,就意味着要限制动态特性。有一些能力要么不能再用、要么需要额外登记。幸运的是,StdUnit.Tags类库家族对NativeAOT的支持良好,仅有两个场景需要特殊注意。

各包就绪情况

分组包状态备注
核心StdUnit.Tags.Core✅
核心StdUnit.Tags✅<Logicet/> 动态插件除外,见下文「<Logicet/> 动态插件在 AOT 下不可用」
扩展StdUnit.Tags.R3Extensions✅
扩展StdUnit.Tags.McpServer✅
扩展StdUnit.Tags.RxExtensions❌底层 System.Reactive 目前对 AOT 支持不好
扩展StdUnit.Tags.BlazorLib.Core❌Blazor Server 模式不支持 AOT
驱动StdUnit.Tags.S7✅
驱动StdUnit.Tags.ModbusTcp✅
驱动StdUnit.Tags.Hjzk✅
驱动StdUnit.Tags.ZLan✅
驱动StdUnit.Tags.OpcUaClient✅
驱动StdUnit.Tags.ComScanner✅
驱动StdUnit.Tags.SimpleFiles✅JSON 测点需登记元数据,见下文「SimpleFiles 的 JSON 测点要自行登记元数据」
  • "✅":该包自己的代码在裁剪 / AOT 分析器下零告警。第三方依赖的 AOT 告警要到 dotnet publish 时才出现(见文末「备注」)。
  • "❌": 由于底层限制,无法支持;或者由于时间不足,尚不支持。

<Logicet/> 动态插件在 AOT 下不可用

这是 .NET NativeAOT 运行时能力问题。NativeAOT 的官方限制里第一条就是 No dynamic loading:运行时的 AssemblyLoadContext 在 AOT 下直接抛 PlatformNotSupportedException。所以"插件 DLL 没被裁剪"并不能救它——宿主根本读不进这个文件。

所以,在 XML 里配了 <Logicet/> 的 AOT 宿主会在加载期抛 TagsProjectNotSupportedException,异常信息类似于:

TagsProjectNotSupportedException: 当前宿主运行时不支持…无法按路径挂载 <Logicet> 指定的 Logicet 插件:plugins/Demo.dll

这里我们有意在加载期抛出异常(快速失败),并推荐两种改法:

  1. 宿主内注册(AOT 下推荐):project.TryAddLogicet<MyLogicet>(sp),逻辑组件跟着宿主一起编译。
  2. 换宿主形态:改用非 AOT(CoreCLR/JIT)发布,<Logicet/> 恢复完整能力(隔离 + 卸载)。

注意,普通 JIT 宿主不受上述影响;net472 上则是另一种降级语义(无隔离、无卸载,见 README 的「netfx 的插件化限制」)。

SimpleFiles 的 JSON 测点要自行登记元数据

JSON 测点的值类型是你自己写的 POCO,框架无法预知它的类型元数据。而 AOT / 裁剪宿主下 System.Text.Json 默认关闭反射序列化(JsonSerializer.IsReflectionEnabledByDefault 为 false),所以,和上面的手动注册ILogicet类似,这里的元数据只能由你在代码里事先注册:

[JsonSerializable(typeof(MyJson))]
internal partial class MyJsonContext : JsonSerializerContext { }
builder.AddSimpleFilesChannel()
       .AddJsonSerializerContext(MyJsonContext.Default)        // ← 只加这一行
       .AddSimpleFilesDirectTagBuilder(
           configure: b => b.WithJsonTagFactory<MyJson>(),
           predicate: b => b.TagDescriptor.TagKind == "Json");

测点的注册方式不变(WithJsonTagFactory<T>() 不带任何类型元数据参数)。在AOT场景下,两种失败都会在构建测点时就报出来,而不是等第一次读写文件:

情况异常怎么改
没登记上下文TagsProjectNotSupportedException加上 AddJsonSerializerContext(...)
登记了上下文,但里面没有该类型的 [JsonSerializable]TagsProjectConfigurationException把该类型加进某个上下文

普通 JIT 宿主不需要登记:没有登记就退回反射序列化,行为与以前完全一致。

备注

IsAotCompatible 只说明本包代码干净。第三方依赖的 AOT 分析要到 dotnet publish 才完全现形,例如 McMaster.NETCore.Plugins会报 IL2104 / IL3053——但是注意,这个依赖包不会对我们的AOT场景有任何影响,因为在我们的代码里一旦在加载期检测到 AOT+动态插件,会当场报错。所以在dotnet publish时,看到关于McMaster.NETCore.Plugins的IL2104、IL3053这两条警告,可以放心忽略。