关于 dotnet-modernize
用于检查现有 .NET 代码现代化机会的技能,可识别过时框架、包、API 模式及缺失的实践。它提供可执行建议,但不负责实施升级。
主要功能
- 01检查目标框架
- 02标记已弃用的包
- 03识别被取代的 API 模式
- 04检查构建配置缺项
- 05指出安全与合规问题
适用场景
- 01查找已停止支持的目标框架
- 02规划包替换工作
- 03定位较旧的代码模式
- 04确定安全与维护问题的优先级
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-modernize安装后在 Claude Code 中输入/dotnet-modernize确认已加载。
详细介绍
dotnet-modernize
分析现有 .NET 代码,寻找现代化机会。识别过时的目标框架、已弃用的包、已被取代的 API 模式,以及缺失的现代最佳实践。针对每项发现提供可执行的建议。
范围边界:此技能仅标记机会。如需了解实际迁移路径、polyfill 策略、多目标框架指导和逐步版本升级流程,请参阅 [skill:dotnet-version-upgrade] 和 [skill:dotnet-multi-targeting]。
**前置条件:**先运行 [skill:dotnet-version-detection],以确定当前 SDK、TFM 和语言版本。运行 [skill:dotnet-project-analysis],了解解决方案结构和依赖项。
交叉引用:[skill:dotnet-project-structure] 介绍现代布局约定,[skill:dotnet-add-analyzers] 介绍基于分析器检测已弃用模式,[skill:dotnet-scaffold-project] 介绍完全现代化项目的目标状态。
现代化检查清单
根据此清单检查现有代码库。每个部分都会说明要查找的内容以及现代替代方案。
1. 目标框架
检查 .csproj 文件(或 Directory.Build.props)中的 <TargetFramework>:
| 当前 TFM | 状态 | 建议 |
|---|---|---|
net8.0 | LTS——支持至 2026 年 11 月 | 计划升级到 net10.0(LTS) |
net9.0 | STS——支持于 2026 年 5 月结束 | 尽快升级到 net10.0 |
net7.0 | 已终止支持 | 立即升级 |
net6.0 | 已终止支持 | 立即升级 |
net5.0 或更低版本 | 已终止支持 | 立即升级 |
netstandard2.0/2.1 | 受支持(库兼容性) | 如果采用多目标框架以扩大覆盖范围,则保留 |
netcoreapp3.1 | 已终止支持 | 立即升级 |
.NET Framework 4.x | 旧版 | 评估迁移可行性 |
扫描所有项目:
# Find all TFMs in the solution
find . -name "*.csproj" -exec grep -h "TargetFramework" {} \; | sort -u
# Check Directory.Build.props
grep "TargetFramework" Directory.Build.props 2>/dev/null
2. 已弃用和已被取代的包
扫描 Directory.Packages.props(或各个 .csproj 文件),查找已被取代的包:
| 已弃用的包 | 替代方案 | 起始版本 |
|---|---|---|
Microsoft.Extensions.Http.Polly | Microsoft.Extensions.Http.Resilience | .NET 8 |
Newtonsoft.Json(新项目) | System.Text.Json | .NET Core 3.0+ |
Microsoft.AspNetCore.Mvc.NewtonsoftJson | 内置 STJ | .NET Core 3.0+ |
Swashbuckle.AspNetCore | 用于生成文档的内置 OpenAPI(Microsoft.AspNetCore.OpenApi);若使用 Swagger UI、筛选器或代码生成,则保留 Swashbuckle | .NET 9 |
NSwag.AspNetCore | 用于生成文档的内置 OpenAPI;若使用客户端生成或 Swagger UI 功能,则保留 NSwag | .NET 9 |
Microsoft.Extensions.Logging.Log4Net.AspNetCore | 内置日志记录 + Serilog 或 OpenTelemetry | .NET Core 2.0+ |
Microsoft.AspNetCore.Authentication.JwtBearer(显式 NuGet 包) | 移除显式 PackageReference——已包含在 Microsoft.AspNetCore.App 共享框架中 | .NET Core 3.0+ |
System.Data.SqlClient | Microsoft.Data.SqlClient | .NET Core 3.0+ |
Microsoft.Azure.Storage.* | Azure.Storage.* | 2020+ |
WindowsAzure.Storage | Azure.Storage.Blobs / Azure.Storage.Queues | 2020+ |
Microsoft.Azure.ServiceBus | Azure.Messaging.ServiceBus | 2020+ |
Microsoft.Azure.EventHubs | Azure.Messaging.EventHubs | 2020+ |
EntityFramework(EF6) | Microsoft.EntityFrameworkCore | .NET Core 1.0+ |
RestSharp(旧版本) | HttpClient + System.Text.Json | .NET Core+ |
AutoMapper | 手动映射或源生成映射器 | 偏好 |
扫描已弃用的包:
# List all package references
grep -rh "PackageVersion\|PackageReference" \
Directory.Packages.props $(find . -name "*.csproj") 2>/dev/null | \
grep -i "Include=" | sort -u
**关于 Newtonsoft.Json 的说明:**大量使用 Newtonsoft.Json 的现有项目(自定义转换器、JObject 操作)可能无法从立即迁移中获益。请标记此项,但评估迁移成本。
3. 已被取代的 API 模式
查找已有现代替代方案的代码模式:
Startup.cs / Program.cs 模式
旧版(.NET 6 之前):
public class Startup
{
public void ConfigureServices(IServiceCollection services) { }
public void Configure(IApplicationBuilder app) { }
}
现代版(最简托管):
var builder = WebApplication.CreateBuilder(args);
// ConfigureServices equivalent
var app = builder.Build();
// Configure equivalent
app.Run();
HttpClient 注册
旧版:
services.AddHttpClient<MyService>(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(300)));
现代版(使用 Microsoft.Extensions.Resilience):
services.AddHttpClient<MyService>(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddStandardResilienceHandler();
同步 I/O
标记: File.ReadAllText、Stream.Read、不带 Async 后缀的 HttpClient。
现代做法: 使用 async 变体——File.ReadAllTextAsync、Stream.ReadAsync、await httpClient.GetAsync()。
热路径中的字符串拼接
标记: 日志记录、循环中使用字符串拼接(+)或 String.Format。
现代做法: 使用字符串插值配合 LoggerMessage 源生成器,或使用 StringBuilder。
旧式集合模式
标记: Hashtable、ArrayList、非泛型集合。
现代做法: 使用 Dictionary<TKey, TValue>、List<T>、泛型集合。
ILogger 模式
旧版:
_logger.LogInformation("Processing order {OrderId}", orderId);
现代版(高性能):
[LoggerMessage(Level = LogLevel.Information, Message = "Processing order {OrderId}")]
static partial void LogProcessingOrder(ILogger logger, string orderId);
4. 缺少现代构建配置
检查是否缺少推荐的构建基础设施:
| 缺少项 | 检查方式 | 建议 |
|---|---|---|
| 集中式包管理 | 没有 Directory.Packages.props | 参见 [skill:dotnet-project-structure] |
| Directory.Build.props | 属性分散在多个 .csproj 文件中 | 集中共享属性 |
| .editorconfig | 仓库根目录没有 .editorconfig | 参见 [skill:dotnet-project-structure] |
| global.json | 没有固定 SDK 版本 | 添加以确保可重复构建 |
| NuGet 审计 | 没有 NuGetAudit 属性 | 在 Directory.Build.props 中启用 |
| 锁定文件 | 没有 RestorePackagesWithLockFile | 启用以确保还原结果确定 |
| 包源映射 | nuget.config 中没有 packageSourceMapping | 添加以保障供应链安全 |
| 分析器 | 没有 AnalysisLevel 或 EnforceCodeStyleInBuild | 参见 [skill:dotnet-add-analyzers] |
| SourceLink | 没有 SourceLink 包引用 | 添加以支持调试器源代码导航 |
| 可空引用类型 | 未启用 <Nullable> | 全局启用 |
| .slnx | 在 .NET 9+ SDK 中仍使用 .sln | 使用 dotnet sln migrate 迁移 |
5. 已弃用的 C# 语言模式
| 旧模式 | 现代替代方式 | 语言版本 |
|---|---|---|
带 case 的 switch 语句 | switch 表达式 | C# 8 |
null != x / x != null 检查 | x is not null | C# 9 |
类型明显时使用 new ClassName() | 目标类型推断的 new() | C# 9 |
| 块范围命名空间 | 文件范围命名空间 | C# 10 |
显式构造函数的 record class | 使用位置参数的 record | C# 10 |
| 手动拼接多行字符串 | 原始字符串字面量("""...""") | C# 11 |
对 INumber<T> 显式分派接口 | 泛型数学接口 | C# 11 |
手动检查 [Flags] 枚举 | 改进的枚举模式匹配 | C# 11+ |
| 没有自然类型的 Lambda | 自然函数类型 | C# 10+ |
手动包装 ValueTask | 使用 ConfigureAwait 模式的 Task/ValueTask | C# 所有版本 |
| 手动编写主构造函数类 | 在 class/struct 上使用主构造函数 | C# 12 |
多个 if/else if 类型检查 | 对类型使用带列表模式的 switch | C# 11+ |
params T[] | params ReadOnlySpan<T>、params 集合 | C# 13 |
使用 object 的锁 | System.Threading.Lock | C# 13 |
6. 安全与合规
| 问题 | 检测方式 | 修复方法 |
|---|---|---|
| 已知漏洞 | dotnet list package --vulnerable | 更新受影响的包 |
| 已弃用的包 | dotnet list package --deprecated | 替换为后续版本 |
| 过时的包 | dotnet list package --outdated | 评估更新 |
| 缺少 HTTPS 重定向 | 没有 app.UseHttpsRedirection() | 添加到管道中 |
| 缺少 HSTS | 没有 app.UseHsts() | 在生产环境中添加 |
| 硬编码密钥 | appsettings.json 中包含连接字符串 | 使用 User Secrets 或 Key Vault |
# Run all NuGet audits
dotnet list package --vulnerable --include-transitive
dotnet list package --deprecated
dotnet list package --outdated
运行现代化扫描
将这些检查组合起来,进行系统化扫描:
# 1. Check TFMs
echo "=== Target Frameworks ==="
find . -name "*.csproj" -exec grep -Hl "TargetFramework" {} \; | while read f; do
echo "$f: $(grep -o '<TargetFramework[s]*>[^<]*' "$f" | head -1)"
done
# 2. Check for deprecated packages
echo "=== Package Audit ==="
dotnet list package --deprecated 2>/dev/null
dotnet list package --vulnerable --include-transitive 2>/dev/null
# 3. Check build infrastructure
echo "=== Build Infrastructure ==="
test -f Directory.Build.props && echo "OK: Directory.Build.props" || echo "MISSING: Directory.Build.props"
test -f Directory.Packages.props && echo "OK: Directory.Packages.props (CPM)" || echo "MISSING: Directory.Packages.props"
test -f .editorconfig && echo "OK: .editorconfig" || echo "MISSING: .editorconfig"
test -f global.json && echo "OK: global.json" || echo "MISSING: global.json"
test -f nuget.config && echo "OK: nuget.config" || echo "MISSING: nuget.config"
# 4. Check for old patterns in code
echo "=== Code Patterns ==="
grep -rl "class Startup" --include="*.cs" . 2>/dev/null && echo "FOUND: Legacy Startup.cs pattern"
grep -rl "Microsoft.Extensions.Http.Polly" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: Deprecated Polly package"
grep -rl "Swashbuckle" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: Swashbuckle (consider built-in OpenAPI for .NET 9+)"
grep -rl "System.Data.SqlClient" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: System.Data.SqlClient (use Microsoft.Data.SqlClient)"
确定现代化改造的优先级
并非所有现代化改造都同样紧迫。请按影响确定优先级:
- 安全性 -- 存在漏洞的包、已结束生命周期的 TFM(不再提供安全补丁)
- 可维护性 -- 已弃用且上游不再维护的包
- 性能 -- 对性能有显著影响的模式(同步调用异步、热路径中使用旧版集合)
- 开发者体验 -- 构建基础设施(CPM、分析器、editorconfig)可改善日常工作流
- 代码风格 -- 语言模式更新的优先级最低,但随着时间推移可以降低认知负担
接下来
此技能会标记现代化改造机会。如需执行升级:
- TFM 版本升级和迁移路径 -- [技能:dotnet-version-upgrade]
- 多目标策略 -- [技能:dotnet-multi-targeting]
- 用于跨版本支持的 Polyfill 包 -- [技能:dotnet-multi-targeting]
- 补充缺失的构建基础设施 -- [技能:dotnet-project-structure]、[技能:dotnet-scaffold-project]
- 配置分析器 -- [技能:dotnet-add-analyzers]
- 添加 CI/CD -- [技能:dotnet-add-ci]