mcpField
M
migrate-dotnet8-to-dotnet9

migrate-dotnet8-to-dotnet9

github.com/dotnet开发5.8k3.5k 次安装1 天前更新
代码仓库

关于 migrate-dotnet8-to-dotnet9

该 Agent 技能指导将 .NET 8 项目或解决方案迁移到 .NET 9,供负责升级和维护 .NET 项目的开发者使用。它按项目技术栈检查兼容性、处理构建与行为变化,并更新部署基础设施。

主要功能

  1. 01评估项目构建、测试及技术栈
  2. 02更新目标框架和 Microsoft 包
  3. 03按技术栈排查编译问题
  4. 04审查 .NET 9 行为变化
  5. 05更新容器及部署配置

适用场景

  1. 01将 net8.0 项目升级到 net9.0
  2. 02处理更新 SDK 后出现的错误和警告
  3. 03适配 ASP.NET Core 9 或 EF Core 9
  4. 04更新 .NET 9 的 Dockerfile 和部署脚本

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill migrate-dotnet8-to-dotnet9

安装后在 Claude Code 中输入/migrate-dotnet8-to-dotnet9确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
aspnet-core-dotnet8to9.md
containers-interop-dotnet8to9.md
core-libraries-dotnet8to9.md
cryptography-dotnet8to9.md
csharp-compiler-dotnet8to9.md
deployment-runtime-dotnet8to9.md
efcore-dotnet8to9.md
sdk-msbuild-dotnet8to9.md
serialization-networking-dotnet8to9.md
winforms-wpf-dotnet8to9.md

详细介绍

.NET 8 → .NET 9 迁移

将 .NET 8 项目或解决方案迁移到 .NET 9,系统地解决所有重大变更。最终项目将以 net9.0 为目标框架,能够干净地构建、通过测试,并涵盖 .NET 9 版本引入的所有行为变更、源代码不兼容变更和二进制不兼容变更。

适用场景

  • 将 TargetFramework 从 net8.0 升级到 net9.0
  • 更新 .NET 9 SDK 后解决构建错误或新增警告
  • 适配 .NET 9 运行时、ASP.NET Core 9 或 EF Core 9 中的行为变更
  • 替换 BinaryFormatter 用法(该功能现在在运行时始终会引发异常)
  • 更新 .NET 9 的 CI/CD 管道、Dockerfile 或部署脚本

不适用场景

  • 项目已面向 net9.0 且能干净地构建——迁移已完成。如果目标是升级到 net10.0,请将 migrate-dotnet9-to-dotnet10 技能作为下一步。
  • 从 .NET 7 或更早版本升级——请先处理之前版本的重大变更
  • 从 .NET Framework 迁移——这是另一项规模更大的工作
  • 从 .NET 9 起步的新项目(无需迁移)

输入

输入必需描述
项目或解决方案路径是要迁移的入口文件:.csproj、.sln 或 .slnx
构建命令否构建方式(例如 dotnet build、仓库构建脚本)。如果未提供,则自动检测
测试命令否运行测试的方式(例如 dotnet test)。如果未提供,则自动检测
项目类型提示否项目是否使用 ASP.NET Core、EF Core、WinForms、WPF、容器等。如果未提供,则根据 PackageReferences 和 SDK 属性自动检测

工作流

直接依据已加载的参考文档作答。 不要搜索文件系统或抓取网页来获取重大变更信息——参考文档包含权威详情。重点是识别适用的重大变更并提供具体修复方案。

提交策略: 在每个逻辑边界处提交——更新 TFM 后(步骤 2)、解决构建错误后(步骤 3)、处理行为变更后(步骤 4),以及更新基础设施后(步骤 5)。这样可以让每次提交都聚焦且便于审查。

步骤 1:评估项目
  1. 确定项目的构建和测试方式。查找构建脚本、.sln/.slnx 文件或单个 .csproj 文件。
  2. 运行 dotnet --version,确认已安装 .NET 9 SDK。如果未安装,请停止并告知用户。
  3. 检查以下内容,确定项目使用了哪些技术领域:
    • SDK 属性:Microsoft.NET.Sdk.Web → ASP.NET Core;Microsoft.NET.Sdk.WindowsDesktop 配合 <UseWPF> 或 <UseWindowsForms> → WPF/WinForms
    • PackageReferences:Microsoft.EntityFrameworkCore.* → EF Core;Microsoft.Extensions.Http → HttpClientFactory
    • 存在 Dockerfile → 需关注容器相关变更
    • 使用 P/Invoke 或本机互操作 → 需关注互操作变更
    • 使用 BinaryFormatter → 需进行序列化迁移
    • 使用 System.Text.Json → 需关注序列化变更
    • X509Certificate 构造函数 → 需关注加密变更
  4. 记录相关的参考文档(参见步骤 3 中的参考文档加载表)。
  5. 在当前 net8.0 目标框架上执行一次干净构建(dotnet build --no-incremental 或删除 bin/obj),以建立干净的基线。记录所有已有警告。
步骤 2:更新目标框架
  1. 在每个 .csproj 文件中(如果已集中配置,则在 Directory.Build.props 中),将:

    <TargetFramework>net8.0</TargetFramework>
    

    改为:

    <TargetFramework>net9.0</TargetFramework>
    

    对于多目标项目,请将 net9.0 添加到 <TargetFrameworks>,或替换 net8.0。

  2. 将所有 Microsoft.Extensions.*、Microsoft.AspNetCore.*、Microsoft.EntityFrameworkCore.* 及其他 Microsoft 包引用更新到 9.0.x 版本。如果使用中央包管理(Directory.Packages.props),请在那里更新版本。

  3. 运行 dotnet restore。留意:

    • 版本要求:.NET 9 SDK 要求使用 Visual Studio 17.12+ 才能以 net9.0 为目标(以 net8.0 及更早版本为目标则需使用 17.11)。
    • 针对 .NET Standard 1.x 和 .NET 7 目标框架 的新警告——请考虑更新或移除过时的目标框架。
  4. 执行干净构建。收集所有错误和新警告。这些问题将在步骤 3 中处理。

步骤 3:解决生成错误和源代码不兼容的更改

系统地处理编译错误和新警告。根据项目类型加载相应的参考文档:

如果项目使用……加载参考文档
任何 .NET 9 项目references/csharp-compiler-dotnet8to9.md
任何 .NET 9 项目references/core-libraries-dotnet8to9.md
任何 .NET 9 项目references/sdk-msbuild-dotnet8to9.md
ASP.NET Corereferences/aspnet-core-dotnet8to9.md
Entity Framework Corereferences/efcore-dotnet8to9.md
Cryptography APIsreferences/cryptography-dotnet8to9.md
System.Text.Json、HttpClient、networkingreferences/serialization-networking-dotnet8to9.md
Windows Forms 或 WPFreferences/winforms-wpf-dotnet8to9.md
Docker containers、native interopreferences/containers-interop-dotnet8to9.md
Runtime configuration、deploymentreferences/deployment-runtime-dotnet8to9.md

需要检查的常见源代码不兼容更改:

  1. params span 重载解析 — String.Join、String.Concat、Path.Combine、Task.WhenAll 等方法新增的 params ReadOnlySpan<T> 重载现在会优先匹配。在 Expression lambda 中调用这些方法的代码会报错(CS8640/CS9226)。请参阅 references/core-libraries-dotnet8to9.md。

  2. StringValues 重载歧义 — params Span<T> 功能会导致 String.Concat、String.Join、Path.Combine 等方法与 StringValues 隐式运算符发生歧义。通过显式转换参数来修复。请参阅 references/core-libraries-dotnet8to9.md。

  3. 新增的过时警告(SYSLIB0054–SYSLIB0057):

    • SYSLIB0054:将 Thread.VolatileRead/VolatileWrite 替换为 Volatile.Read/Volatile.Write
    • SYSLIB0057:将 X509Certificate2/X509Certificate 的二进制/文件构造函数替换为 X509CertificateLoader 方法
    • 另有 SYSLIB0055(ARM AdvSimd 有符号重载)和 SYSLIB0056(使用哈希算法的 Assembly.LoadFrom)——请参阅 references/core-libraries-dotnet8to9.md
  4. C# 13 在 record struct 上使用 InlineArray — 现在禁止在 record struct 类型上使用 [InlineArray] 特性(CS9259)。请改用常规 struct。请参阅 references/csharp-compiler-dotnet8to9.md。

  5. C# 13 迭代器安全上下文 — C# 13 中的迭代器现在会引入安全上下文。在迭代器内部、使用外层 unsafe 类所继承的不安全代码的本地函数现在会报错。请为本地函数添加 unsafe 修饰符。请参阅 references/csharp-compiler-dotnet8to9.md。

  6. C# 13 集合表达式重载解析 — 空集合表达式([])不再通过 span 与非 span 进行重载决胜。现在会优先选择元素类型完全匹配的重载。请参阅 references/csharp-compiler-dotnet8to9.md。

  7. 已移除 String.Trim(params ReadOnlySpan<char>) — 针对 .NET 9 预览版编译、且向 Trim/TrimStart/TrimEnd 传递 ReadOnlySpan<char> 的代码必须重新生成;此重载已在正式版中移除。请参阅 references/core-libraries-dotnet8to9.md。

  8. BinaryFormatter 始终会抛出异常 — 如果项目使用 BinaryFormatter,请停止并告知用户——这是一个重大决策。请参阅 references/serialization-networking-dotnet8to9.md。

  9. HttpListenerRequest.UserAgent 可为 null — 此属性现在为 string?。请添加 null 检查。请参阅 references/serialization-networking-dotnet8to9.md。

  10. Windows Forms 可空性注解更改 — 某些 WinForms API 参数已从可空改为不可空。请更新调用点。请参阅 references/winforms-wpf-dotnet8to9.md。

  11. Windows Forms 安全分析器(WFO1000) — 新增的分析器会针对未显式配置序列化的属性报错。请参阅 references/winforms-wpf-dotnet8to9.md。

每批修复后都要再次生成。重复此过程,直至生成通过且无错误。

步骤 4:处理行为变更

行为变更不会导致生成错误,但可能会改变运行时行为。请检查每个适用项,并确定之前的行为是否被依赖。

影响较大的行为变更(优先检查):

  1. 浮点数到整数的转换现在采用饱和处理 — 在 x86/x64 上,从 float/double 到整数类型的转换现在会采用饱和处理,而不再回绕。请参阅 references/deployment-runtime-dotnet8to9.md。

  2. EF Core:待处理模型变更异常 — 如果模型存在待处理变更,Migrate()/MigrateAsync() 现在会引发异常。请在任何 HasData 调用中搜索 DateTime.Now、DateTime.UtcNow 或 Guid.NewGuid(),并将其替换为固定常量(例如,new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc))。请参阅 references/efcore-dotnet8to9.md。

  3. EF Core:显式事务异常 — 在用户事务中调用 Migrate() 现在会引发异常。请参阅 references/efcore-dotnet8to9.md。

  4. HttpClientFactory 默认使用 SocketsHttpHandler — 将主要处理程序强制转换为 HttpClientHandler 的代码会导致 InvalidCastException。请参阅 references/serialization-networking-dotnet8to9.md。

  5. HttpClientFactory 默认会对标头进行隐藏处理 — Trace 级别日志中的所有标头值现在都会被隐藏。请参阅 references/serialization-networking-dotnet8to9.md。

  6. 环境变量的优先级高于 runtimeconfig.json — 环境变量中的运行时配置设置现在会覆盖 runtimeconfig.json。请参阅 references/deployment-runtime-dotnet8to9.md。

  7. ASP.NET Core 在开发环境中启用 ValidateOnBuild/ValidateScopes — HostBuilder 现在默认会在开发环境中启用 DI 验证。请参阅 references/aspnet-core-dotnet8to9.md。

需要检查的其他行为变更(可能导致运行时异常 ⚠️ 或细微的行为差异):

  • ⚠️ FromKeyedServicesAttribute 不再注入非键控服务作为回退 — 会引发 InvalidOperationException
  • ⚠️ 容器映像不再安装 zlib — 依赖系统 zlib 的应用将无法运行
  • ⚠️ Intel CET 现在默认启用 — 与 CET 不兼容的本机库可能导致进程终止
  • BigInteger 的最大长度现在为 (2^31) - 1 位
  • JsonDocument 对 JSON null 的反序列化现在会返回非空的 JsonDocument,其 JsonValueKind 为 Null,而不是 C# null
  • System.Text.Json 元数据读取器现在会对元数据属性名称取消转义
  • ZipArchiveEntry 名称/注释现在会遵循 UTF-8 标志
  • IncrementingPollingCounter 的初始回调现在是异步的
  • InMemoryDirectoryInfo 会将 rootDir 添加到文件路径前面
  • RuntimeHelpers.GetSubArray 返回的类型有所不同
  • PictureBox 会引发 HttpRequestException,而不是 WebException
  • StatusStrip 使用不同的默认呈现器
  • IMsoComponent 支持现在需要显式启用
  • SafeEvpPKeyHandle.DuplicateHandle 会增加句柄的引用计数
  • HttpClient 指标现在始终报告 server.port
  • HttpClient EventSource 事件和 IHttpClientFactory 日志中的 URI 查询字符串现在会被隐藏
  • dotnet watch 与旧版框架的 Hot Reload 不兼容
  • WPF GetXmlNamespaceMaps 返回 Hashtable,而不是 String
步骤 5:更新基础设施
  1. Dockerfile:更新基础映像。请注意,.NET 9 容器映像不再安装 zlib。如果应用依赖 zlib,请在 Dockerfile 中添加 RUN apt-get update && apt-get install -y zlib1g。

    # Before
    FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
    FROM mcr.microsoft.com/dotnet/aspnet:8.0
    # After
    FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
    FROM mcr.microsoft.com/dotnet/aspnet:9.0
    
  2. CI/CD 管道:更新 SDK 版本引用。如果使用 global.json,请更新:

    {
      "sdk": {
        "version": "9.0.100",
        "rollForward": "latestFeature"
      }
    }
    

    检查 rollForward 策略——如果设为 "disable" 或 "latestPatch",升级后 SDK 可能无法正确解析。"latestFeature"(推荐)允许 SDK 自动切换到最新的 9.0.x 功能带。

  3. Visual Studio 版本:.NET 9 SDK 需要 VS 17.12+ 才能以 net9.0 为目标。VS 17.11 只能以 net8.0 及更早版本为目标。

  4. 终端记录器:现在,dotnet build 在交互式终端中默认使用终端记录器。解析 MSBuild 控制台输出的 CI 脚本可能需要使用 --tl:off 或 MSBUILDTERMINALLOGGER=off。

  5. dotnet workload 输出:输出格式已更改。请更新解析工作负载命令输出的脚本。

  6. .NET Monitor 映像:标签已简化为仅包含版本(这会影响引用特定标签的容器编排)。

步骤 6:验证
  1. 执行完整的干净构建:dotnet build --no-incremental
  2. 运行所有测试:dotnet test
  3. 如果应用已容器化,请构建并测试容器映像
  4. 对应用执行冒烟测试,特别注意:
    • BinaryFormatter 的使用(将在运行时抛出异常)
    • 浮点数转换为整数的行为
    • EF Core 迁移的应用
    • HttpClientFactory 处理程序的类型转换和日志记录
    • 开发环境中的 DI 验证
    • 运行时配置设置(环境变量优先级)
  5. 检查差异,确保没有引入意外的行为变更

参考文档

references/ 文件夹包含按技术领域整理的详细重大变更信息。仅加载与正在迁移的项目相关的参考资料:

参考文件加载时机
references/csharp-compiler-dotnet8to9.md始终加载(C# 13 编译器重大变更——记录上的 InlineArray、迭代器安全上下文、集合表达式重载)
references/core-libraries-dotnet8to9.md始终加载(适用于所有 .NET 9 项目)
references/sdk-msbuild-dotnet8to9.md始终加载(SDK 和构建工具变更)
references/aspnet-core-dotnet8to9.md项目使用 ASP.NET Core
references/efcore-dotnet8to9.md项目使用 Entity Framework Core
references/cryptography-dotnet8to9.md项目使用 System.Security.Cryptography 或 X.509 证书
references/serialization-networking-dotnet8to9.md项目使用 BinaryFormatter、System.Text.Json、HttpClient 或网络 API
references/winforms-wpf-dotnet8to9.md项目使用 Windows Forms 或 WPF
references/containers-interop-dotnet8to9.md项目使用 Docker 容器或本机互操作(P/Invoke)
references/deployment-runtime-dotnet8to9.md项目使用运行时配置、部署,或包含浮点数转换为整数的操作

评论

支持 Markdown