.NET现代化分析 dotnet-modernize

该技能用于分析现有.NET代码库,识别现代化机会,包括过时的目标框架、已弃用的包、被替代的API模式以及缺失的现代最佳实践,并提供可操作的建议。关键词:.NET现代化、代码分析、框架检测、包管理、API模式、升级建议。

后端开发 0 次安装 0 次浏览 更新于 3/6/2026

名称: dotnet-modernize 描述: “分析.NET代码以进行现代化。过时的TFMs、已弃用的包、被替代的模式。”

dotnet-modernize

分析现有.NET代码以识别现代化机会。检测过时的目标框架、已弃用的包、被替代的API模式以及缺失的现代最佳实践。为每个发现提供可行建议。

范围

  • 过时目标框架检测
  • 已弃用包识别
  • 被替代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 传统 评估迁移可行性

扫描所有项目:

# 查找解决方案中的所有TFMs
find . -name "*.csproj" -exec grep -h "TargetFramework" {} \; | sort -u

# 检查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 内置日志 + SerilogOpenTelemetry .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 手动映射或源生成映射器 偏好

扫描已弃用包:

# 列出所有包引用
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等效
var app = builder.Build();
// Configure等效
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.ReadAllTextStream.Read、不带Async后缀的HttpClient

现代: 使用async变体——File.ReadAllTextAsyncStream.ReadAsyncawait httpClient.GetAsync()

热路径中的字符串连接

标记: 字符串连接(+)或String.Format在日志记录、循环中。

现代: 使用字符串插值配合LoggerMessage源生成器,或StringBuilder

传统集合模式

标记: HashtableArrayList、非泛型集合。

现代: 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 添加以增强供应链安全
分析器 AnalysisLevelEnforceCodeStyleInBuild 参见[skill:dotnet-add-analyzers]
SourceLink 无SourceLink包引用 添加以实现调试器源导航
可为空引用类型 未启用<Nullable> 全局启用
.slnx 仍使用.sln配合.NET 9+ SDK 使用dotnet sln migrate迁移

5. 已弃用的C#语言模式

旧模式 现代替代方案 语言版本
caseswitch语句 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手动包装 Task/ValueTask配合ConfigureAwait模式 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中的连接字符串 使用用户密钥或密钥保管库
# 运行所有NuGet审计
dotnet list package --vulnerable --include-transitive
dotnet list package --deprecated
dotnet list package --outdated

运行现代化扫描

将检查组合成系统扫描:

# 1. 检查TFMs
echo "=== 目标框架 ==="
find . -name "*.csproj" -exec grep -Hl "TargetFramework" {} \; | while read f; do
  echo "$f: $(grep -o '<TargetFramework[s]*>[^<]*' "$f" | head -1)"
done

# 2. 检查已弃用包
echo "=== 包审计 ==="
dotnet list package --deprecated 2>/dev/null
dotnet list package --vulnerable --include-transitive 2>/dev/null

# 3. 检查构建基础设施
echo "=== 构建基础设施 ==="
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. 检查代码中的旧模式
echo "=== 代码模式 ==="
grep -rl "class Startup" --include="*.cs" . 2>/dev/null && echo "FOUND: 旧Startup.cs模式"
grep -rl "Microsoft.Extensions.Http.Polly" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: 已弃用Polly包"
grep -rl "Swashbuckle" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: Swashbuckle(考虑.NET 9+的内置OpenAPI)"
grep -rl "System.Data.SqlClient" --include="*.csproj" --include="*.props" . 2>/dev/null && echo "FOUND: System.Data.SqlClient(使用Microsoft.Data.SqlClient)"

优先化现代化

并非所有现代化都同样紧迫。按影响优先排序:

  1. 安全——有漏洞的包、生命周期结束的TFMs(无安全补丁)
  2. 可支持性——已弃用且无上游维护的包
  3. 性能——具有显著性能影响的模式(同步over-async、热路径中的传统集合)
  4. 开发人员体验——构建基础设施(CPM、分析器、editorconfig)改善日常工作流程
  5. 代码风格——语言模式更新是优先级最低的,但随时间减少认知负担

下一步

此技能标记现代化机会。对于执行升级:

  • TFM版本升级和迁移路径——[skill:dotnet-version-upgrade]
  • 多目标策略——[skill:dotnet-multi-targeting]
  • 跨版本支持的polyfill包——[skill:dotnet-multi-targeting]
  • 添加缺失的构建基础设施——[skill:dotnet-project-structure]、[skill:dotnet-scaffold-project]
  • 配置分析器——[skill:dotnet-add-analyzers]
  • 添加CI/CD——[skill:dotnet-add-ci]

参考