GJJ.Keystone.ArchitectureGuard 4.2.2

dotnet add package GJJ.Keystone.ArchitectureGuard --version 4.2.2
                    
NuGet\Install-Package GJJ.Keystone.ArchitectureGuard -Version 4.2.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GJJ.Keystone.ArchitectureGuard" Version="4.2.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GJJ.Keystone.ArchitectureGuard" Version="4.2.2" />
                    
Directory.Packages.props
<PackageReference Include="GJJ.Keystone.ArchitectureGuard" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GJJ.Keystone.ArchitectureGuard --version 4.2.2
                    
#r "nuget: GJJ.Keystone.ArchitectureGuard, 4.2.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GJJ.Keystone.ArchitectureGuard@4.2.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GJJ.Keystone.ArchitectureGuard&version=4.2.2
                    
Install as a Cake Addin
#tool nuget:?package=GJJ.Keystone.ArchitectureGuard&version=4.2.2
                    
Install as a Cake Tool

GJJ.Keystone.ArchitectureGuard

面向 GJJ 微服务的架构守护测试库。在 *.Tests 项目里跑,违规即让单元测试失败、CI 红灯; 报告带颜色、严重度分组、修复建议、文件超链接(IDE 可点击跳转)。

核心承诺:零运行时依赖(不引 ASP.NET / Microsoft.Extensions.Logging),只在 CI / 本地测试期参与。

适用版本:3.0.7+

为什么独立成包

  • GJJ.Keystone.Abstractions 应保持精简,只放契约
  • GJJ.Keystone.Toolkit 提供运行时无关的通用工具代码
  • GJJ.Keystone.AspNetCore 引入了 ASP.NET Core 概念,而本库的职责之一恰好是让非 Web 层免受这些概念污染

把架构规则放在独立程序集里,可避免把 Web 依赖拉入只需要在 CI / 测试期检查的项目。

速查

你想知道 看哪一节
有哪些规则 / 严重度 / 我违规会怎样 二、规则全集
怎么在我的 *.Tests 项目里接入 三、典型用法
失败时报告长什么样 / 怎么去掉颜色 四、输出格式与颜色
历史违规怎么豁免 五、基线管理(IgnoreFiles)
怎么扩展自定义规则 六、扩展自定义规则
严重度怎么映射到 CI 行为 七、严重度模型
已知限制 / 误报特征 八、已知限制

一、模块全景

┌──────────────────────────────────────────────────────────────┐
│   ArchitectureGuardOptions                                   │
│   - RootDirectory                                            │
│   - IgnoredDirectoryNames / IgnoredRelativeFilePaths        │
│   - HttpContextProtectedLayers                               │
│   - ControlledContextFieldNames                              │
│   - ViewModelDirectoryNames                                  │
│   - AspNetCoreProtectedProjectSegments                       │
└──────────────────────────────────────────────────────────────┘
       ↓ ArchitectureGuard.Scan / ScanGjjDefaults
┌──────────────────────────────────────────────────────────────┐
│   IArchitectureRule × 18                                     │
│   - 文本扫描(SourceLineReader 剥离注释 / 字符串)            │
│   - PathClassifier 判定层(Application/Infrastructure/...)  │
│   - 每条规则带 DefaultSeverity + Suggestion                  │
└──────────────────────────────────────────────────────────────┘
       ↓
┌──────────────────────────────────────────────────────────────┐
│   ArchitectureGuardResult                                    │
│   - Violations: IReadOnlyList<ArchitectureViolation>         │
│   - Format(): 带颜色 / 分组 / 修复建议的报告                  │
│   - ThrowIfFailed(): xUnit 断言失败入口                       │
└──────────────────────────────────────────────────────────────┘
       ↓ 进入 xUnit 测试输出
       (终端: 渲染颜色 / IDE: 渲染加粗下划线斜体)
关键类型 文件 用途
ArchitectureGuard ArchitectureGuard.cs 静态扫描入口(Scan / ScanGjjDefaults)
ArchitectureGuardOptions ArchitectureGuardOptions.cs 扫描根目录 + 规则可配置集合
ArchitectureGuardResult ArchitectureGuardResult.cs 扫描结果 + Format() / ThrowIfFailed()
ArchitectureViolation ArchitectureViolation.cs 单条违规(RuleId / FilePath / Line / Message / Severity / Suggestion)
ArchitectureSeverity ArchitectureSeverity.cs 严重度枚举(Info / Warning / Error / Critical)
ViolationFormatOptions ViolationFormatOptions.cs 渲染选项(UseColor / ShowSuggestions / ShowPassingBanner)
IArchitectureRule IArchitectureRule.cs 规则接口(RuleId / Description / DefaultSeverity / Evaluate)
GjjDefaultArchitectureRules GjjDefaultArchitectureRules.cs 默认规则集装配(19 条)
Internal/PathClassifier 内部 层 / 文件归类(Controller / Application / ...)
Internal/SourceLineReader 内部 文本扫描器(剥离注释;可选保留字符串内容)
Internal/ClassScanner 内部 类级扫描器:聚合 partial class、检查类上 / 类体内 attribute
Internal/ViolationReportRenderer 内部 ANSI 着色 / 分组 / 80 列换行

二、规则全集(19 条)

按主题分组。每条规则一旦命中:

  • 严重度 ≥ Error 的违规默认让 ThrowIfFailed() 抛 InvalidOperationException
  • 严重度 = Warning / Info 不阻断(但会显示在报告里)

如何调整某条规则的严重度:在调用 Scan(...) 时传入自定义 IArchitectureRule 替换默认实例,覆写 DefaultSeverity。

分层 / DTO 边界(6 条)

ID 规则 默认严重度 检测点
GJJ001 ForbiddenHttpContext Error 非 Web 层(Application/Domain/Repository/Infrastructure/Model)不得依赖 HttpContext / IHttpContextAccessor / HttpRequest / HttpResponse / ISession / IFormCollection / IFormFile / IWebHostEnvironment / IHostingEnvironment / RouteData / RouteValueDictionary;也不得继承 Controller / ControllerBase
GJJ002 ControllerDtoControlledFields Error Controller 入参 DTO(Controllers/**/DTOs/C_*.cs)与响应 ViewModel(Controllers/**/ViewModels/*VM.cs)不得暴露由服务端上下文控制的字段。默认字段:OperatorId、CreatedBy、ModifiedBy、UpdatedBy、CreateTime、CreatedTime、ModifiedTime、UpdateTime、UpdatedTime、IsDeleted、Deleted、IpAddress、ClientIp、UserAgent、RequestId、TraceId、CorrelationId、SessionId、TenantId
GJJ003 CrossLayerDtoUsage Warning Controller 出参必须用 C_ DTO 或 *VM;Application 不得引用 C_ DTO / *VM / 任意 .Api.* 子命名空间;Infrastructure / Domain / Model 不得引用任何 A_ / C_ / *VM 类型
GJJ004 ProjectFileForbiddenReference Error 项目名含 .Application / .Domain / .Model / .Infrastructure 的 .csproj 禁止引用 Microsoft.AspNetCore.App / .Http / .Mvc / .Authentication / .Authorization / .Cors / .Routing / .HttpOverrides / Swashbuckle.AspNetCore / Serilog.AspNetCore
GJJ019 KeystonePackageExclusivity Error 同一 .csproj 不得同时引用 GJJ.Keystone.AspNetCore 与 GJJ.Keystone.AspNetCore.Gateway(两包共享命名空间,同引必 CS0433;业务服务用主包、网关宿主用轻量包)
GJJ005 SmEncryptionRuntimeChecks Critical *SMEncryptionMiddleware*.cs 必须同时引用 INonceStore / TryConsumeNonceAsync 与 IsWithinClockSkew / MaxClockSkewSeconds;且 MaxClockSkewSeconds = N 字面量须 ≤ 300 秒(M1 P0 防重放底线)

异步 / 通用代码风险(2 条)

ID 规则 默认严重度 检测点
GJJ006 SyncOverAsync Error 在非测试 / 非 Program.cs / 非 Mappings-Profiles-Configurations 目录下出现 .Result、.Wait()、.GetAwaiter().GetResult()(线程池死锁源头)
GJJ010 SwallowAllExceptions Warning catch (Exception ...) 块的整个 body 内既无 throw 也无 Log/logger 调用(典型"吞异常")

安全 / 合规(7 条)

ID 规则 默认严重度 检测点
GJJ007 HardcodedSecrets Critical 源码字面量内出现 password=、apiKey=、secret=、连接串里 Password=...、"Bearer <20+ chars>" 等硬编码秘密
GJJ008 WeakCryptoApi Critical 使用 MD5 / SHA1 / DESCryptoServiceProvider / TripleDES / RijndaelManaged / CipherMode.ECB
GJJ009 UnsafeDeserialization Critical BinaryFormatter / NetDataContractSerializer / TypeNameHandling.All-Auto-Objects(RCE 风险)
GJJ011 RawSqlInterpolation Critical FromSqlRaw($"...") / ExecuteSqlRaw($"...") 等 EF Core *Raw 接口接收字符串插值(SQL 注入)
GJJ012 InsecureCookie Error new CookieOptions { ... } 缺 Secure = true / HttpOnly = true / SameSite = 任一
GJJ017 CorsAllowAnyOrigin Critical .AllowAnyOrigin() / .WithOrigins("*")
GJJ018 LoggingPii Error Logger 调用模板含 {password} / {token} / {idCard} / {mobile} / {bankCard} / {身份证} / {手机} / {密码} 等敏感占位符

架构纪律(4 条)

ID 规则 默认严重度 检测点
GJJ013 DomainEntityInController Error Controller 文件 using *.Domain* 或 public 方法签名含 *Entity / *Aggregate 后缀类型
GJJ014 RepositoryInController Error Controller 字段 / 构造参数直接持有 *Repository / I*Repository 类型
GJJ015 DbContextOutsideInfra Error DbContext 派生与字段必须位于 Infrastructure / Repository / *.JobService / *.Worker / *.HostedService / *.BackgroundService 项目
GJJ016 MissingAuthorize Info / Error(自适应) Controller 文件没有任何 [Authorize] 或 [AllowAnonymous] 标注。严重度按项目实际授权配置自动选择:扫描到 requireAuthenticatedByDefault: false 或 FallbackPolicy = null → Error(未标 = 真公开);否则 → Info(FallbackPolicy 已保护)。详见下方 GJJ016 特别说明。
GJJ016 特别说明

GJJ016 与 GJJ.Keystone.AspNetCore/Auth/JwtAuthExtensions.cs 的 AddJwtAuth 协同设计:

public static IServiceCollection AddJwtAuth(
    this IServiceCollection services,
    Action<JwtAuthOptions> configure,
    bool requireAuthenticatedByDefault = true,   // ★ 默认 true
    ILogger? startupLogger = null)
{
    // ...
    services.AddAuthorization(options =>
    {
        if (requireAuthenticatedByDefault)
        {
            options.FallbackPolicy = new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                .RequireAuthenticatedUser()
                .Build();
        }
    });
}

关键事实:当 requireAuthenticatedByDefault = true(默认),ASP.NET Core 授权管线注册 FallbackPolicy = RequireAuthenticatedUser()——这意味着所有未标注授权属性的端点都默认需要认证。

因此 Controller 三种状态的真实含义:

Controller 标注 框架行为 安全风险 reviewer 关注度
不标 FallbackPolicy 强制认证 无(已认证) 低
[Authorize] 显式认证 无 低(语义同默认)
[AllowAnonymous] 显式破除默认认证 取决于业务 高(真正的公开端点)

GJJ016 严重度自适应:规则会扫描全仓库源码自动决定严重度,无需手动配置:

检测到的信号 严重度 含义
requireAuthenticatedByDefault: false(在任何 .cs 文件里) Error Keystone AddJwtAuth 关闭了 FallbackPolicy,未标 = 真公开 → 阻断
FallbackPolicy = null(手写关 fallback) Error 直接关掉 ASP.NET Core 内置 fallback → 阻断
都没检测到(默认 / 显式 true / 仓库没用 AddJwtAuth) Info 假设 FallbackPolicy 已保护 → 仅可读性提示

实现见 Rules/MissingAuthorizeRule.cs:DetectEffectiveSeverity。

强制升级到 Error(绕过自动检测)示例:

// 不论 FallbackPolicy 状态,强制所有 Controller 必须显式标授权
public sealed class StrictMissingAuthorizeRule : IArchitectureRule
{
    private readonly MissingAuthorizeRule _inner = new();
    public string RuleId => _inner.RuleId;
    public string Description => _inner.Description;
    public ArchitectureSeverity DefaultSeverity => ArchitectureSeverity.Error;
    public IEnumerable<ArchitectureViolation> Evaluate(ArchitectureScanContext ctx)
        => _inner.Evaluate(ctx).Select(v => v with { Severity = ArchitectureSeverity.Error });
}

// 装配
var rules = GjjDefaultArchitectureRules.Create()
    .Where(r => r.RuleId != "GJJ016")
    .Concat(new[] { new StrictMissingAuthorizeRule() })
    .ToArray();
ArchitectureGuard.Scan(options, rules).ThrowIfFailed();

三、典型用法

3.1 最简调用(推荐起点)

using GJJ.Keystone.ArchitectureGuard;

public sealed class ArchitectureGuardTests
{
    [Fact]
    public void GJJ_default_architecture_rules_should_pass()
    {
        var options = new ArchitectureGuardOptions
        {
            RootDirectory = LocateRepositoryRoot(),
        };

        ArchitectureGuard.ScanGjjDefaults(options).ThrowIfFailed();
    }

    private static string LocateRepositoryRoot()
    {
        var dir = new DirectoryInfo(AppContext.BaseDirectory);
        while (dir != null)
        {
            if (dir.EnumerateFiles("*.sln").Any())
                return dir.FullName;
            dir = dir.Parent;
        }
        throw new DirectoryNotFoundException("repo root (含 *.sln) 未找到");
    }
}

ThrowIfFailed() 在违规时抛 InvalidOperationException,消息体就是带颜色 + 分组 + 修复建议的报告。

3.2 自定义规则集(跳过部分规则 / 改严重度)

var result = ArchitectureGuard.Scan(options,
    new ForbiddenHttpContextDependencyRule(),
    new SmEncryptionRuntimeChecksRule(),
    // ...只跑你关心的规则
    );

3.3 项目特有受控字段(在默认集合上扩展)

options.ControlledContextFieldNames.UnionWith(new[]
{
    "DbPointCode",   // 多数据库路由
    "ChannelCode",   // 渠道标识
    "SubjectId",     // 业务主体 ID
});

3.4 自定义忽略目录(如本项目特殊产物目录)

options.IgnoredDirectoryNames.Add(".claude");
options.IgnoredDirectoryNames.Add("artifacts");

四、输出格式与颜色

4.1 实际样例(带颜色版会在终端 / Rider / VS Code 渲染)

================================================================================
  GJJ Architecture Guard — 23 violation(s) across 4 rule(s)        ← 加粗
================================================================================

  [CRITICAL] 1 violation(s)                                        ← 亮红+粗
--------------------------------------------------------------------------------
  GJJ005  SMEncryptionMiddleware 必须同时具备 nonce 去重 ...         ← 亮红+粗
    Demo/Security/SmEncryptionMiddleware.cs:1                      ← 下划线
      SMEncryptionMiddleware 缺少 nonce 一次性消费校验……
    fix: 注入 INonceStore 并在解密前调用 TryConsumeNonceAsync...   ← 斜体

  [ERROR]    1 violation(s)                                        ← 红+粗
--------------------------------------------------------------------------------
  GJJ001  非 Web 层代码不得依赖 HttpContext 相关 API。
    Demo.Application/News/NewsService.cs:7
      非 Web 层禁止依赖 HttpContext 相关 API 'HttpContext'……
    fix: 在 Controller 内提取所需值(OperatorId、ClientIp 等)……

  [WARNING]  1 violation(s)                                        ← 黄+粗
--------------------------------------------------------------------------------
  GJJ003  DTO 不得跨层泄漏……
    Demo.Infrastructure/News/NewsRepository.cs:14
      ...
    fix: ...

================================================================================
  Summary: Critical=1  Error=1  Warning=1  Info=0                  ← 各色加粗
================================================================================

4.2 颜色控制

场景 做法
终端 dotnet test,想看颜色 默认即开
CI 日志想抑制 ANSI 设环境变量 NO_COLOR=1 或 TERM=dumb
旧 IDE 测试面板把 \x1b[ 显示成乱码 shell 里 export NO_COLOR=1
测试代码里强制无色 result.Format(new ViolationFormatOptions { UseColor = false })

4.3 ViolationFormatOptions

public sealed record ViolationFormatOptions
{
    public bool? UseColor { get; init; }            // null = 自动检测
    public bool  ShowSuggestions { get; init; } = true;
    public bool  ShowPassingBanner { get; init; }   // 通过时也打印"PASSED"横幅
}

五、基线管理(IgnoreFiles)

历史违规一次性塞进 baseline 让 CI 绿;新写违规当场拦截。

var options = new ArchitectureGuardOptions { RootDirectory = root };

options.IgnoreFiles(
    // GJJ001:历史代码非 Web 层依赖 HttpContext
    "GJJ.UniServiceHub.Application/Admin/AdminService.cs",
    "GJJ.UniServiceHub.Infrastructure/Admin/AdminCenterClient.cs",
    // GJJ002:响应 ViewModel 含 createTime(出参视为合理)
    "GJJ.UniServiceHub.Api/Controllers/.../SysUserInfoVM.cs"
);

ArchitectureGuard.ScanGjjDefaults(options).ThrowIfFailed();

5.1 何时加 baseline

  • 历史代码违规,团队没排期治理
  • 文本扫描误报(如 HttpRequestMessage 字面量含 "HttpRequest" 子串)
  • 框架/平台规定的合法跨层(特殊代理转发)

5.2 何时不能加 baseline

  • 新代码引入的违规 → 必须修代码
  • Critical 级别(GJJ005/007/008/009/011/017)→ 改代码或评审豁免,不应静默

baseline 是技术债,应随 sprint 逐项清理。


六、扩展自定义规则

6.1 实现 IArchitectureRule

using GJJ.Keystone.ArchitectureGuard;
using GJJ.Keystone.ArchitectureGuard.Internal;

public sealed class MyProjectSpecificRule : IArchitectureRule
{
    private const string FixSuggestion = "改用 IGjjCurrentUser 注入,不直接读 HttpContext.User。";

    public string RuleId => "GJJ100";
    public string Description => "禁止在 Application 层直接读 HttpContext.User.Claims。";
    public ArchitectureSeverity DefaultSeverity => ArchitectureSeverity.Error;

    public IEnumerable<ArchitectureViolation> Evaluate(ArchitectureScanContext context)
    {
        foreach (var file in context.SourceFiles.Where(PathClassifier.IsApplication))
        {
            foreach (var (lineNumber, text) in SourceLineReader.NonCommentLines(file))
            {
                if (!text.Contains("HttpContext.User", StringComparison.Ordinal)) continue;

                yield return new ArchitectureViolation(
                    RuleId, file.RelativePath, lineNumber,
                    "Application 层禁止直接读 HttpContext.User.Claims。",
                    Severity: DefaultSeverity,
                    Suggestion: FixSuggestion);
            }
        }
    }
}

6.2 接入

ArchitectureGuard.Scan(options,
    new MyProjectSpecificRule(),
    // 还可以叠加默认集
    new ForbiddenHttpContextDependencyRule(),
    // ...
).ThrowIfFailed();

6.3 助手 API(Internal)

测试项目通过 InternalsVisibleTo 可用,也是写自定义规则的好朋友:

API 用途
PathClassifier.IsApplication(file) 文件是否在 Application 层
PathClassifier.IsInfrastructure(file) 同上 Infrastructure
PathClassifier.IsController(file) 路径含 Controllers/
PathClassifier.IsControllerDto(file) 入参 DTO(C_*.cs in DTOs/)
PathClassifier.IsControllerViewModel(file, dirs) 响应 VM(*VM.cs in ViewModels/)
PathClassifier.IsInProtectedLayer(file, layers) 是否在受保护层中
PathClassifier.IsTestProject(file) *.Tests / *.Test / tests/
SourceLineReader.NonCommentLines(file) 逐行扫源码(剥离注释 + 字符串内容)
SourceLineReader.NonCommentLines(file, keepStringContents: true) 同上但保留字符串内容(适合检测硬编码字面量)
ClassScanner.EnumerateClassDeclarations(files) 遍历所有 class 声明(注释 / 字符串中的伪声明已剥)
ClassScanner.BuildClassIndex(files) className → 所有声明位置(聚合 partial class 跨文件)
ClassScanner.ClassHasAttribute(decl, regex) 检查类声明上方连续 attribute + 类体内是否带某 attribute
ClassScanner.AnyPartialHasAttribute(decls, regex) partial class 任一分片带该 attribute 即视为已声明

6.4 何时该用 ClassScanner

如果你的规则需要回答**"某个类是否带某 attribute"或"某个类是否包含某成员"**这种 类级问题——用 ClassScanner。

它已处理三类共性边界:

  • 一文件多类(不同类各自独立判定)
  • partial class 分散在多文件(attribute 标在任一分片都算)
  • 注释 / 字符串中的伪 attribute(不误判)

不要在新规则里再写"扫文件全文找 attribute"——交给 ClassScanner。


七、严重度模型

级别 数值 默认 CI 行为 适用场景
Critical 3 ThrowIfFailed 抛异常 安全 / 合规 P0 红线(数据泄漏、RCE、SQL 注入、弱加密)
Error 2 ThrowIfFailed 抛异常 架构 / 安全边界(必须修复)
Warning 1 不阻断 应当修复但允许逐步治理
Info 0 不阻断 提示信息

ThrowIfFailed() 默认在任意违规时抛异常(包含 Warning)。如果只想 Error 及以上阻断 CI,自己控制:

var result = ArchitectureGuard.ScanGjjDefaults(options);
var blocking = result.Violations
    .Where(v => v.Severity >= ArchitectureSeverity.Error)
    .ToList();

if (blocking.Count > 0)
    throw new InvalidOperationException(result.Format());

八、已知限制

8.1 文本扫描,非完整词法

  • 不解析 C# 11 原始字符串字面量("""..."""),出现在受保护层会触发误报——避免使用或加 IgnoreFiles
  • 病态代码模式(极端嵌套、宏拼接)可能误报
  • M8 排期升级到 Roslyn Analyzer 后误报会大幅消失

8.2 规则范围限定

规则 必然误报场景 处理建议
GJJ006 AutoMapper / FluentValidation 配置类同步等待 默认已豁免 Mappings/Profiles/Configurations 目录
GJJ010 业务有意 swallow(清理 / 重试外层) 加 IgnoreFiles
GJJ013 Controller 同名空间下"非真 Controller"类 规则只检查路径含 Controllers/,可调整目录结构
GJJ015 独立 Job / Worker 项目 默认已识别 .JobService / .Worker / .HostedService / .BackgroundService 后缀
GJJ016 文件只放数据契约不放真 Controller 整 class 取名时去掉 Controller 后缀

8.3 不会做

  • 不检测运行时行为(鉴权链是否真生效、注入是否真发生)——是静态文本扫描
  • 不读取 / 修改源码(只读)
  • 不联网

九、跑测试 / CI 集成

# 全 sln 测试
dotnet test GJJMicroserviceKit/GJJMicroserviceKit.sln

# 只跑架构守护
dotnet test --filter "FullyQualifiedName~ArchitectureGuardTests"

# 抑制 ANSI(CI 日志友好)
NO_COLOR=1 dotnet test ...

GitHub Actions 片段:

- name: Architecture Guard
  env:
    NO_COLOR: "1"      # CI 不渲染 ANSI
  run: |
    dotnet test GJJ.UniServiceHub/GJJ.UniServiceHub.Tests \
      --filter "FullyQualifiedName~ArchitectureGuardTests" \
      --no-build

十、版本历史

版本 主要变更
3.0.8 GJJ016 修正:严重度自适应——扫描 requireAuthenticatedByDefault: false / FallbackPolicy = null 时自动升 Error;其他情况维持 Info(FallbackPolicy 已保护)。无需用户手动配置。<br>新增 Internal/ClassScanner 共享类级扫描:处理一文件多类(#5)、partial class 跨文件(#6)、注释/字符串伪 attribute(#7)三类边界;GJJ016 改用之,判定精度提升。
3.0.7 新增 GJJ006-018 共 13 条规则;GJJ001-005 补强;GJJ006/015 默认豁免调参
3.0.6 输出报告重设计:严重度分组 + 颜色 / 加粗 / 斜体 / 下划线 + 修复建议;ViolationFormatOptions
3.0.x 新增 GJJ005(SM 中间件守护)
3.x 初版规则集(GJJ001-GJJ004)
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.2.2 143 7/3/2026
4.2.1 120 7/1/2026
4.2.0 131 6/5/2026
4.0.0 115 5/22/2026
3.0.10 112 5/13/2026
3.0.9 118 5/11/2026
3.0.8 112 5/11/2026
3.0.7 113 5/8/2026
3.0.6 107 5/6/2026
3.0.5 107 5/6/2026
3.0.4 104 5/6/2026
3.0.3 110 4/30/2026
3.0.2 115 4/30/2026
3.0.0 124 4/29/2026