ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MessagePack-CSharp 源码生成器诊断 MsgPack003:为被引用类型补齐 `[MessagePackObject]` 标注

MessagePack-CSharp 源码生成器诊断 MsgPack003:为被引用类型补齐 `[MessagePackObject]` 标注 序列化后端【免费下载链接】MessagePack-CSharpExtremely Fast MessagePack Serializer for C#(.NET, .NET Core, Unity, Xamarin). / msgpack.org[C#]项目地址https://gitcode.com/gh_mirrors/me/MessagePack-CSharp点击查看免费下载本篇文章讲解 MessagePack-CSharp 源码生成器Source Generator附带的 Roslyn 分析器规则MsgPack003Use MessagePackObjectAttribute当某个被[MessagePackObject]类型通过[Key]字段或属性引用的类型自身缺少[MessagePackObject]标注时该规则会以 Error 级诊断阻止编译。读完本文你将掌握该规则的触发条件、标准修复与自动代码修复的用法以及使用MessagePackAssumedFormattable声明自定义 formatter 负责该类型的替代方案并能理解其与源码生成器 formatter 发现机制的底层关系。规则速览诊断 ID、严重级别与判定逻辑MsgPack003 由 MsgPack00xMessagePackAnalyzer.cs 中的UseMessagePackObjectAttributeId常量定义ID 为MsgPack003对应TypeMustBeMessagePackObject诊断描述符其关键元数据如下项目值说明诊断 IDMsgPack003规则唯一标识标题Use MessagePackObjectAttribute提示需要标注[MessagePackObject]消息格式Type must be marked with MessagePackObjectAttribute: {0}{0}为违规类型名分类Usage属于用法类问题默认严重级别Error默认开启直接阻断编译Help LinkAnalyzerUtilities.GetHelpLink(MsgPack003)指向本规则文档该规则的核心判定是所有被可序列化成员引用的类型自身也必须被标注[MessagePackObject]或属于内建支持的类型。这是保证 MessagePack 序列化体系完整性的基础约束——只有被标注的类型源码生成器才可能为它生成 formatter详见下文为什么需要这条规则一节。分析器通过AnalyzeSymbol遍历编译单元中的命名类型对带[MessagePackObject]的 class/struct 调用TypeCollector.Collect收集其成员进而对成员引用的类型检查其是否具备可格式化能力无法证明可格式化的类型即触发TypeMustBeMessagePackObject。该诊断由 doc/analyzers/MsgPack003.md 文档正式定义并在 AnalyzerReleases.Shipped.md 中登记发布。触发场景被引用类型缺少[MessagePackObject]文档给出的典型违规模式如下类A已标注[MessagePackObject]其成员b带有[Key(0)]但被引用的类B没有任何 MessagePack 相关标注[MessagePackObject] public class A { [Key(0)] public B b; } public class B { public int Count; }此时分析器会在B类型处报告MsgPack003Type must be marked with MessagePackObjectAttribute: B。注意即使B的成员类型如int本身是内建可序列化类型只要B自身没有标注整个类型图就无法闭合序列化时便没有可用的 formatter 来描述B的布局。从源码结构看可推断的触发范围测试文件 MsgPack00xAnalyzerTests.cs 中的用例多数标记了[Fact(Skip ...)]等待测试基础设施更新但源码清晰地展示了分析器的预期行为覆盖了多种触发形态属性成员public Foo Member { get; set; }中的Foo未标注时触发字段成员public Foo Member;同样触发可空引用类型/可空值类型public Foo? Member;同样触发泛型容器元素public ListFoo Member;中容器内层元素Foo未标注时触发record 类型普通 record 属性以及 record 主构造函数参数public record Bar([property: MessagePack.Key(0)] Foo Member);均适用Union 场景测试Union用例展示了接口标注[MessagePack.Union(0, typeof(Foo))]后被注册的Foo实现类型若未标注[MessagePackObject]也会触发MsgPack003——即 Union 子类型同样必须可格式化。由此可以推断该规则面向类型图中的每个节点都必须可被 formatter 覆盖的闭合性检查并不因成员形态属性/字段/可空/泛型/record不同而放宽。标准修复为被引用类型补齐标注修复思路是让B成为一个合法的 MessagePack 对象。文档给出的修复示例[MessagePackObject] public class A { [Key(0)] public B b; } [MessagePackObject] public class B { [Key(0)] public int Count; }要点有两条给B加上[MessagePackObject]声明它参与 MessagePack 序列化给B的每个可序列化成员加上[Key]数字键或字符串键皆可这与另一条规则MsgPack004Attribute properties and fields of MessagePack objects的要求一致——[MessagePackObject]类型的所有成员要么带[Key]要么带[IgnoreMember]。补齐标注后源码生成器即可为B生成对应的 formatterA的成员引用随之闭合。自动代码修复一键补全属性该诊断附带自动代码修复code fix。文档明确说明An automated code fix is offered for this.在测试工程中该修复由 MessagePackCodeFixProvider.cs 提供测试用例如AddAttributeToType_Properties、AddAttributeToType_Fields展示了修复的预期输出修复器会自动为违规类型添加[MessagePackObject]并为每个成员补上[Key(0)]、[Key(1)]…… 的递增数字键例如// 修复前报告 MsgPack003 public class Foo { public string Member { get; set; } } [MessagePackObject] public class Bar { [Key(0)] public Foo Member { get; set; } } // 修复后 [MessagePackObject] public class Foo { [Key(0)] public string Member { get; set; } } [MessagePackObject] public class Bar { [Key(0)] public Foo Member { get; set; } }在 Visual Studio 或 VS Code 中将光标置于诊断波浪线处或打开错误列表应用代码修复Ctrl.即可选择该修复无需手工逐个补齐标注。替代修复用MessagePackAssumedFormattable声明外部 formatter当B由自定义 formatter负责格式化例如实现了IMessagePackFormatterT且通过自定义 resolver 注册你并不想给它加[MessagePackObject]标注时可以改用文档提供的抑制方案——在程序集级别声明该类型被假定为可格式化[assembly: MessagePackAssumedFormattable(typeof(B))]添加该声明后分析器在检查到B被其他[MessagePackObject]类型引用时不再报告MsgPack003。责任约定必须确保 formatter 能被 resolver 发现文档对此有明确的责任提示使用该属性后你自行负责确保B的自定义 formatter 能通过MessagePackSerializerOptions.Resolver所持有的IFormatterResolver被找到。换言之仅声明假定可格式化并不会自动注册 formatter运行时若 resolver 找不到对应 formatter反序列化仍会失败。从源码看该属性定义于 AnalyzerAttributes.cs 第 44-57 行[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module, AllowMultiple true)] [Conditional(NEVERDEFINED)] // We only need this attribute for analysis, so we dont want it to be included in the users built assembly. public class MessagePackAssumedFormattableAttribute : Attribute { public MessagePackAssumedFormattableAttribute(Type formattableType) { this.FormattableType formattableType; } public Type FormattableType { get; } }值得注意的实现细节程序集/模块级、可多次使用AttributeTargets.Assembly | AttributeTargets.Module配合AllowMultiple true意味着可以一次性声明多个类型[Conditional(NEVERDEFINED)]该特性不会真正编译进你的程序集元数据仅用于编译期分析因此不会带来运行时开销分析器通过读取编译单元的程序集特性context.Compilation.Assembly.GetAttributes()解析它随后并入AnalyzerOptions.AssumedFormattableTypes见 AnalyzerOptions.cs同一文件还定义了更推荐的MessagePackKnownFormatterAttributeMessagePackKnownFormatterAttribute当自定义 formatter 类型本身可被源码生成器发现时应优先使用它把 formatter 显式纳入生成的 resolver而非仅假定可格式化。两种属性在AnalyzerUtilities.ParseAssumedFormattableAttribute/ParseKnownFormatterAttribute中被解析共同影响分析器对可格式化类型集合的判定。为什么需要这条规则与源码生成器的闭合性要求MsgPack003 不是一条孤立的风格规则它与 MessagePack-CSharp 源码生成器的工作方式直接相关Formatter 是按类型生成的[MessagePackObject]类型会触发 MessagePackGenerator 为其生成Formatter类生成器要求每个被序列化的类型都能解析到对应的 formatter内建、自定义或生成。类型图必须闭合A序列化时需要把成员B一并写出若B既无[MessagePackObject]生成 formatter、又无自定义 formatter 可查序列化链路在运行时必然中断。MsgPack003 把这个运行时问题提前到编译期暴露。Error 级、默认开启因此该规则不允许静默放行强制开发者明确表态——要么给B标注走生成路径要么声明MessagePackAssumedFormattable/MessagePackKnownFormatter走自定义 formatter 路径。该规则与系列分析器共同构成一套编译期校验体系MsgPack004 约束成员必须有[Key]/[IgnoreMember]MsgPack005 校验[MessagePackObject]定义合法性键唯一、键类型一致等MsgPack012 要求数据类型至少 internal 可见性以便生成 formatter 访问MsgPack011 要求含私有可序列化成员的类型声明为 partial。实践中修复MsgPack003时往往需要连带满足这些相邻规则才能让类型真正进入可序列化状态。小结触发[MessagePackObject]类型的[Key]成员引用了未标注的类型含属性/字段/可空/泛型元素/record/Union 子类型等形态标准修复为被引用类型补[MessagePackObject]与[Key]或使用自动代码修复一键完成替代修复程序集级声明[assembly: MessagePackAssumedFormattable(typeof(B))]前提是自定义 formatter 确实可通过MessagePackSerializerOptions.Resolver发现本质保证每个被序列化类型都有 formatter 可用的类型图闭合性将运行时序列化失败提前为编译错误。相关参考规则定义与实现见 MsgPack00xMessagePackAnalyzer.cs、MsgPack003.md特性定义见 AnalyzerAttributes.cs测试用例见 MsgPack00xAnalyzerTests.cs分析器选项对假定可格式化类型的合并逻辑见 AnalyzerOptions.cs。赞分享序列化后端【免费下载链接】MessagePack-CSharpExtremely Fast MessagePack Serializer for C#(.NET, .NET Core, Unity, Xamarin). / msgpack.org[C#]项目地址https://gitcode.com/gh_mirrors/me/MessagePack-CSharp点击查看免费下载相关推荐27款Bootswatch主题如何高效挑选用官方实时预览页缩略图做决策的实战指南27款Bootswatch主题如何高效挑选用官方实时预览页缩略图做决策的实战指南 还在为 Bootstrap 界面千篇一律而烦恼吗 Bootswatch序列化后端PHPStan 团队落地指南从 0 到 1 集成到 GitHub Actions CI/CD 的完整流程PHPStan 团队落地指南从 0 到 1 集成到 GitHub Actions CI/CD 的完整流程 PHPStan 是一款强大的 PHP 静态分析工具序列化后端Browserless配置精讲从TOKEN到CONCURRENT环境变量完整清单Browserless配置精讲从TOKEN到CONCURRENT环境变量完整清单 Browserless 是一个基于 Docker 部署无头浏览器Headl序列化后端上一篇boto3 DynamoDB事务隔离级别并发控制详解下一篇WarriorJS行业应用从游戏到企业级AI解决方案的迁移创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表