You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Roslyn Analyzer检查只读字段的MessageKey唯一性

问题描述

项目内存在数百个分散在多类、多项目中的错误码定义,形式如下:

public readonly ErrorMessageCode 00001 = new ErrorMessageCode()
{
    MessageKey = "00001",
    Title = "Error!",
    Message = "You did something wrong!"
};

由于MessageKey是数据库主键,要求全局唯一,希望通过自定义Roslyn Analyzer Rule实现重复MessageKey的自动检查,目前已有自定义规则的依赖基础,但从未编写过此类跨项目的唯一性检查规则。

实现方案

完全可以实现这类全局唯一性检查,核心思路是通过Roslyn分析整个解决方案的语义模型,收集所有MessageKey值并比对重复,具体步骤如下:

1. 识别目标字段与初始化器

在Analyzer中注册语法分析器,定位所有符合以下特征的代码节点:

  • 字段修饰符包含public readonly
  • 字段类型为ErrorMessageCode
  • 字段初始化使用对象初始化器(new ErrorMessageCode() { ... })

2. 提取MessageKey属性值

遍历对象初始化器中的所有属性赋值节点,筛选出MessageKey对应的赋值语句,提取其字符串字面量的值。核心逻辑示例:

// 假设node是对象初始化器节点(ObjectCreationExpressionSyntax)
var initializer = node.Initializer;
foreach (var assignment in initializer.Expressions.OfType<AssignmentExpressionSyntax>())
{
    if (assignment.Left is IdentifierNameSyntax identifier && identifier.Identifier.Text == "MessageKey")
    {
        if (assignment.Right is LiteralExpressionSyntax literal)
        {
            var messageKey = literal.Token.ValueText;
            // 收集messageKey用于后续检查
        }
    }
}

3. 跨项目收集与去重检查

由于错误码分散在多个项目,需要启用解决方案级分析:

  • 使用Roslyn的IncrementalGenerator或注册支持解决方案级的Analyzer,确保能遍历所有项目的编译单元
  • 维护一个全局HashSet<string>存储已收集的MessageKey,每处理一个字段时:
    • 若当前MessageKey已存在,在对应的赋值位置报告重复错误诊断
    • 若不存在,将其加入集合

4. 复用现有自定义规则基础

如果已有自定义规则的依赖类,可直接复用:

  • 复用已有的DiagnosticDescriptor定义(指定错误ID、标题、描述等)
  • 复用规则注册逻辑,将新分析器添加到规则集中
关键注意事项
  • 确保Analyzer能访问到ErrorMessageCode类型的语义信息,避免因项目引用问题导致无法识别类型
  • 对于非字符串字面量的动态MessageKey赋值,可添加诊断提示,要求必须使用固定字面量,保证检查有效性
  • 测试时需覆盖跨项目的重复场景,验证解决方案级分析的正确性

内容的提问来源于stack exchange,提问作者RedSonja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:22:05