ARTICLE DETAIL

资讯详情

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

Stride 引擎 STRDIAG 分析器规则全解析:序列化契约的 Roslyn 静态检查清单

Stride 引擎 STRDIAG 分析器规则全解析:序列化契约的 Roslyn 静态检查清单 游戏开发图形学VR【免费下载链接】strideStride (formerly Xenko), a free and open-source cross-platform C# game engine.项目地址https://gitcode.com/gh_mirrors/st/stride点击查看免费下载Stride 游戏引擎原 Xenko在sources/core/Stride.Core.CompilerServices中内置了一套基于 Roslyn 的 C# 诊断分析器DiagnosticAnalyzer通过STRDIAG000STRDIAG011一组规则在编译期检查数据序列化契约的正确性。本文以 AnalyzerReleases.Shipped.md 这一官方规则发布清单为骨架结合 Analyzers 目录下的全部规则源码与 AnalyzerTests 测试用例逐条解析每条规则的触发条件、诊断消息与底层判定逻辑帮助你在编写可被 Stride 序列化系统正确处理的[DataContract]/[DataMember]类型时避开全部编译期陷阱。1. 规则发布清单文件是什么AnalyzerReleases.Shipped.md采用微软 Roslyn 分析器社区标准的Release Tracking发布追踪文件格式该格式规范由 dotnet/roslyn-analyzers 仓库中的ReleaseTrackingAnalyzers.Help.md定义用于记录分析器产品对外发布的规则清单;开头的行是注释## Release 1.0表示一次已发布的规则版本### New Rules小节下用表格列出新增规则列包括Rule ID、Category规则分类、Severity严重级别与Notes诊断标识符。对应的 AnalyzerReleases.Unshipped.md 则记录尚未随正式版本发布的规则当前未发布清单中只有一条STRDIAG011。2. STRDIAG 规则总览以下是发布清单 1.0 版中的全部 10 条已发布规则连同未发布的STRDIAG011一并列出Rule IDCategorySeverity诊断标识符NotesSTRDIAG000SerializationWarningSTRDIAG000AttributeContradictionSTRDIAG001SerializationWarningSTRDIAG001InvalidDataContractSTRDIAG002SerializationWarningSTRDIAG002InvalidContentModeSTRDIAG003SerializationWarningSTRDIAG003InaccessibleMemberSTRDIAG004SerializationWarningSTRDIAG004PropertyWithNoGetterSTRDIAG005SerializationWarningSTRDIAG005ReadonlyMemberTypeIsNotSupportedSTRDIAG006SerializationWarningSTRDIAG006InvalidAssignModeSTRDIAG007SerializationWarningSTRDIAG007DataMemberOnDelegateSTRDIAG008SerializationWarningSTRDIAG008FixedFieldInStructsSTRDIAG009SerializationWarningSTRDIAG009InvalidDictionaryKeySTRDIAG010SerializationWarningSTRDIAG010InvalidConstructorSTRDIAG011未发布BuildWarningSTRDIAG011UndeclaredProjectAssetExtension从源码可以确认的通用实现事实见 DiagnosticCategory.cs每条规则都以DiagnosticSeverity.Warning且isEnabledByDefault: true创建即默认启用无需额外开启规则分类只有两种Serialization序列化契约检查与Build构建资产管线检查所有诊断都带有helpLinkUri格式为https://doc.stride3d.net/latest/en/diagnostics/{RuleId}.html即每条规则都有对应的在线文档页所有分析器在Initialize中都调用context.EnableConcurrentExecution()开启并发执行并对生成代码执行分析ConfigureGeneratedCodeAnalysis(Analyze | ReportDiagnostics)保证大规模编译下的性能。3. 已发布规则逐条解析Release 1.0STRDIAG000特性自相矛盾Attribute Contradiction触发条件同一成员上同时标注[DataMember]与[DataMemberIgnore]。修复豁免若成员同时标注了[DataMemberUpdatable]则矛盾组合被视为合法不触发诊断。原因从 STRDIAG000AttributeContradiction.cs 的源码注释可知[DataMember]与[DataMemberIgnore]是互斥声明只有当[DataMemberUpdatable]明确表达此成员允许被更新的意图时这一组合才有意义。诊断消息There is an Attribute Contradiction on {0} Member. [DataMemberIgnore] Attribute on a [DataMember] is not supported. Except if it has also [DataMemberUpdatable] Attribute.实现要点分析器通过WellKnownReferences从当前编译单元解析DataMemberAttribute、DataMemberIgnoreAttribute与DataMemberUpdatableAttribute。注意DataMemberUpdatableAttribute位于Stride.Engine而非Stride.Core因此当目标项目未引用Stride.Engine时该符号可能为null此时只要成员同时带有前两个特性即直接报错。测试佐证STRDIAG000_Test.cs 验证了属性、字段两种载体以及[DataMemberIgnore][DataMember]与[DataMember][DataMemberIgnore]两种顺序都会触发而单独使用[DataMember]、单独使用[DataMemberIgnore]、或三者共注含[DataMemberUpdatable]均不报错。STRDIAG001无效的 [DataContract]触发条件标注了[DataContract]的类型对序列化器不可见或类型为file局部类型IsFileLocal。诊断消息The [DataContract] is not valid for the type {0}. Expected is a public/internal Accessor.实现要点见 STRDIAG001InvalidDataContract.cs。通过IsVisibleToSerializer(hasDataMemberAttribute: true)判定即带有[DataMember]语境下的可见性要求为public、internal或internal protected判定逻辑见下文第 4 节。STRDIAG002无效的 Content 模式触发条件成员以DataMemberMode.Content模式声明为数据成员但其类型是不可变类型字符串、基元类型或值类型/结构体。诊断消息The DataMemberMode.Content is not valid for the member {0}. Only mutable reference types are supported for DataMemberMode.Content Mode members.实现要点见 STRDIAG002InvalidContentMode.cs。DataMemberMode枚举定义在 DataMemberMode.csDefault 0、Assign 1、Content 2、Never 4。Content 模式要求反序列化时逐成员恢复内容而非整对象替换因此只能用于类引用类型成员字符串被当作不可变类型处理。STRDIAG003不可访问的成员触发条件标注[DataMember]的字段或属性对序列化器不可访问。诊断消息The member {0} with [DataMember] is not accessible to the serializer. Only public/internal/internal protected visibility is supported, when the [DataMember] attribute is applied.实现要点见 STRDIAG003InaccessibleMember.cs。与 STRDIAG001 共用IsVisibleToSerializer可见性判定。STRDIAG004无 Getter 的属性触发条件标注[DataMember]的属性没有 getter或 getter 的可见性不足以被序列化器访问。诊断消息两条变体The property {0} with [DataMember] does not have a getter which is required for serialization The property {0} with [DataMember] does not have an accessible getter which is required for serialization. A public/internal/internal protected getter is expected.实现要点见 STRDIAG004PropertyWithNoGetter.cs。该分析器注册了两个DiagnosticDescriptor一个针对getter 不存在GetMethod is null一个针对getter 存在但可见性不足。读取序列化必须经由 getter因此这是硬性要求。STRDIAG005只读成员的类型不受支持触发条件只读成员字段为readonly或属性没有可访问的 setter标注[DataMember]且其类型为不可变类型。诊断消息The [DataMember] Attribute is applied to a read-only member {0} with a non supported type. Only mutable reference types are supported for read-only members.实现要点见 STRDIAG005ReadonlyMemberTypeIsNotSupported.cs。字段分支检查IsReadOnly属性分支检查SetMethod为null或 setter 不可访问再结合IsImmutableType()判定类型。逻辑是只读成员只能通过内容模式Content逐成员恢复被填充而不可变类型无法这样做。STRDIAG006无效的 Assign 模式触发条件成员声明为DataMemberMode.Assign枚举值 1但属性没有 setter或 setter 不可被序列化器访问。诊断消息Invalid DataMembermode for the specified [DataMember] member {0}. A public/internal/internal protected setter is required for DataMemberMode.Assign.实现要点见 STRDIAG006InvalidAssignMode.cs。Assign 模式要求反序列化时用 YAML 数据构造新对象并整体赋值给成员因此必须具备可访问的 setter。分析器通过HasDataMemberMode(context, dataMemberAttribute, dataMemberMode, 1)读取[DataMember(Mode DataMemberMode.Assign)]的构造参数并比对枚举值。STRDIAG007委托类型成员不可序列化触发条件标注[DataMember]的字段或属性的类型是委托TypeKind.Delegate。诊断消息Invalid [DataMember] Attribute on the member {0}. A Delegate is not serializable.实现要点见 STRDIAG007DataMemberOnDelegate.cs。事件与委托类型在 Stride 的 YAML 序列化管线中无法持久化属于硬性禁用。STRDIAG008结构体中的 fixed 缓冲区字段触发条件位于[DataContract]结构体中的fixed大小缓冲区字段且未标注[DataMemberIgnore]。诊断消息Struct members with the fixed Modifier are not supported as a Serialization target on member {0}实现要点见 STRDIAG008FixedFieldInStructs.cs。判定依据是IFieldSymbol.IsFixedSizeBuffer。由于fixed缓冲属于非托管内存布局无法被反射式序列化器处理若确实不需要持久化应显式加[DataMemberIgnore]豁免。STRDIAG009无效的字典键类型触发条件标注[DataMember]的成员实现IDictionaryTKey, TValue且键类型不是基元类型、string或枚举。诊断消息The member {0} implements IDictionaryT,K with an unsupported type for the key. Only primitive types ( like int,float,.. ) are supported or string or enums as the Dictionary Key in asset serialization. When used in other contexts the warning may not apply and can be suppressed.实现要点见 STRDIAG009InvalidDictionaryKey.cs。分析器遍历符号类型的所有接口匹配IDictionary,的原始定义后检查TypeArguments[0]字段分支要求IsImmutableType()基元、string、值类型属性分支额外允许枚举TypeKind.Enum。诊断消息本身明确提示在其他上下文可能不适用可以抑制此警告——这是设计上的有意识取舍。STRDIAG010缺少公开无参构造函数触发条件[DataContract]类型含通过Inherited true继承得到数据契约的类型没有公开的无参构造函数。诊断消息The Type {0} doesnt have a public parameterless constructor, which is needed for Serialization实现要点见 STRDIAG010InvalidConstructor.cs。判定逻辑为type.Constructors.Any(x x.Parameters.Length 0 x.DeclaredAccessibility Accessibility.Public)。抽象类型被跳过IsAbstract直接返回。对未直接标注[DataContract]的类型会沿BaseType链向上查找[DataContract(Inherited true)]特性通过命名参数Inherited判断继承得到契约的类型同样需要公开无参构造。测试佐证STRDIAG010_Test.cs 覆盖了默认构造、空构造、多构造含无参与有参、仅有参构造报错、[DataContract(Inherited true)]继承场景报错以及 C# 主构造函数primary constructor报错等多种情形。4. 未发布规则 STRDIAG011项目资产扩展名未声明该规则当前记录在 AnalyzerReleases.Unshipped.md尚未随正式版本发布分类为Build。触发条件实现IProjectAsset接口的资产类型通过[AssetDescription]声明了文件扩展名但该扩展名未出现在构建属性StrideProjectAssetExtensions中。诊断消息Asset type {0} declares file extension {1}, which is missing from StrideProjectAssetExtensions. Append it in the projects build .targets so the asset compiler captures it into the .sdbuild manifest.为什么重要从 STRDIAG011UndeclaredProjectAssetExtension.cs 的头部注释可见StrideProjectAssetExtensions是决定哪些项目源码文件会进入.sdbuild清单的构建属性遗漏扩展名会导致这些资产被静默丢弃silently drops those assets。实现要点只在引用了Stride.Core.Assets的编译单元中生效IProjectAsset与AssetDescriptionAttribute解析失败即静默返回跳过.cs扩展名C# 源码编译进程序集本就不是资产编译输入以及生成器资产实现IProjectFileGeneratorAsset的类型如可视化脚本声明集合通过build_property.StrideProjectAssetExtensionsForAnalyzer全局选项读取。源码注释解释了这一设计editorconfig 中;是注释符无法承载列表因此构建系统传递了一份以逗号分隔的副本分析器内用ParseExtensions按,/;切分、统一小写并确保前缀.。构建侧对应配置在 Sdk.targets 中shader 文件.sdsl、.sdfx被发现后会追加到StrideProjectAssetExtensions属性其他自定义项目资产类型需在项目自己的.targets中追加对应扩展名否则编译期就会收到本规则的警告。5. 底层判定机制公共基础设施所有分析器都依赖Common目录下的三个辅助类理解它们就能理解整套规则的判定哲学。WellKnownReferences跨编译解析特性符号WellKnownReferences.cs 负责从当前Compilation中解析出DataMemberAttribute、DataMemberIgnoreAttribute、DataMemberUpdatableAttribute、DataContractAttribute、DataMemberMode、IDictionary,、IProjectAsset、AssetDescriptionAttribute等符号。所有分析器都以RegisterCompilationStartAction为入口在编译开始时解析一次符号再注册RegisterSymbolAction监听具体的SymbolKindProperty、Field、NamedType。当目标项目不引用相应程序集例如不引用Stride.Engine导致DataMemberUpdatableAttribute缺失时分析器会直接返回、保持静默避免误报。SymbolExtensions可见性与类型判定SymbolExtensions.cs 提供三个核心判定方法IsVisibleToSerializer这是整套规则的核心语义。标注了[DataMember]的成员可见性要求放宽为public、internal或internal protectedProtectedOrInternal未标注[DataMember]的成员则严格要求public。这解释了 STRDIAG001/003/004/005/006 等规则统一使用的可被序列化器访问标准IsImmutableTypestring或任何非引用类型结构体、基元、枚举等值类型都被视为不可变类型——源码注释明确说明这是因为 YAML 序列化器无法用反射处理值类型HasDataMemberMode读取[DataMember(Mode ...)]的构造参数并与目标枚举值比对STRDIAG002Content2与 STRDIAG006Assign1依赖它。DiagnosticsAnalyzerHelper统一报告入口DiagnosticsAnalyzerHelper.cs 提供ReportDiagnostics扩展方法遍历符号的所有Locations为每个位置生成一条以符号名填充消息格式的诊断。6. 分析器如何接入项目构建从 Stride.Core.CompilerServices.csproj 可以看到该项目以netstandard2.0单目标框架构建引用Microsoft.CodeAnalysis.Analyzers、Microsoft.CodeAnalysis.CSharp与PolySharp并开启EnforceExtendedAnalyzerRules这是标准 Roslyn 分析器工程配置。在 Sdk.targets 中Stride 的 SDK 目标会将Stride.Core.CompilerServices项目以OutputItemTypeAnalyzer、ReferenceOutputAssemblyfalse的方式作为分析器引用注入到除其自身之外的所有项目。因此任何使用 Stride SDK 的项目都会自动获得这套 STRDIAG 规则无需额外安装 NuGet 包或修改项目文件。使用提示由于所有规则默认启用且为 Warning 级别它们会在 IDEVisual Studio / Rider / VS Code Roslyn与命令行构建中同时生效若某条规则在当前场景不适用例如 STRDIAG009 在非资产序列化上下文中的字典可以通过标准的.editorconfig或#pragma warning disable按规则 ID 单独抑制不会影响其他规则每条规则的helpLinkUri都指向官方诊断文档IDE 中点击警告即可跳转查阅。7. 如何验证与测试这套分析器分析器配套了完整的 xUnit 测试工程Stride.Core.CompilerServices.Tests其中 AnalyzerTests 目录为 STRDIAG000STRDIAG010 各提供一份测试文件如 STRDIAG000_Test.cs。测试模式高度一致通过ClassTemplates模板构造带[DataContract]的最小测试类型用TestHelper.ExpectDiagnosticAsync(sourceCode, DiagnosticId)断言某段代码应触发指定规则用TestHelper.ExpectNoDiagnosticsAsync(sourceCode)断言修正后的代码不再触发。例如 STRDIAG000 的测试分别验证了属性/字段上的矛盾特性、特性顺序反转[DataMember][DataMemberIgnore]与反向均报错而单独使用任一特性或同时带[DataMemberUpdatable]时静默通过。这套测试既是规则行为的回归保障也是理解每条规则边界条件的最直接教材。8. 小结Stride 的 STRDIAG 分析器套件把数据契约必须可序列化这条约定从运行时错误前移到编译期可见性public/internal/internal protected、getter/setter 存在性、只读成员与不可变类型的组合约束、DataMemberMode与成员能力的匹配、委托与fixed缓冲的禁用、字典键类型限制、公开无参构造函数要求以及项目资产扩展名的构建清单声明全部可由编译器静态判定。实际开发中遵循这些规则意味着你的[DataContract]类型天然满足 Stride YAML 序列化管线与资产编译器.sdbuild清单的要求从根源上避免资产静默丢失与运行时反序列化失败。进一步阅读规则发布清单AnalyzerReleases.Shipped.md、AnalyzerReleases.Unshipped.md分析器源码目录sources/core/Stride.Core.CompilerServices/Analyzers公共基础设施DiagnosticCategory.cs、SymbolExtensions.cs数据成员模式枚举DataMemberMode.cs构建接线Sdk.targets规则测试sources/core/Stride.Core.CompilerServices.Tests/AnalyzerTests赞分享游戏开发图形学VR【免费下载链接】strideStride (formerly Xenko), a free and open-source cross-platform C# game engine.项目地址https://gitcode.com/gh_mirrors/st/stride点击查看免费下载相关推荐mbedtls代码静态分析规则加密库安全检查清单mbedtls代码静态分析规则加密库安全检查清单 1. 配置检查 配置检查是确保mbedtls库安全的基础步骤。需验证 mbedtls_config.h ht网络安全密码学通信嵌入式SlackTextViewController 静态代码分析规则自定义 Clang 检查器SlackTextViewController 静态代码分析规则自定义 Clang 检查器 SlackTextViewController 作为一款已停止维护UI组件移动开发Wasmtime静态分析规则代码质量自动化检查Wasmtime静态分析规则代码质量自动化检查 你是否还在为WebAssembly项目的代码质量担忧是否希望通过自动化工具提前发现潜在问题本文将深入解析W语言运行时JIT编译编译器上一篇微服务架构可靠性终极指南10个关键容错机制与高可用设计实践下一篇RedInk基于FlaskVue的模块化AI图文生成架构解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表