第一次在一个 PR 里看到同事删掉了熟悉的 .sln、提交了一个 .slnx 文件时,我第一反应是皱了皱眉。.sln 用了这么多年,怎么说换就换?而且当时团队里还有几个人用的 Visual Studio 版本比较旧,这个文件提交上去,他们第一件事就是找我来“兴师问罪”。但又不得不承认,那个 PR 的 diff 确实干净得反常——以前动一下解决方案文件动不动就冒出几十行改动,那次只改了几行。
也正是那次经历,让我花了很长时间把 .slnx 从里到外研究了一遍,顺带把团队里一堆构建脚本、CI 配置、工具链逐个排查了一遍。这篇文章就把我实际验证过的结论、踩过的坑和取舍逻辑整理出来。无论你是个把 Visual Studio 当作日常编辑器的 .NET 开发者,还是要管一堆仓库和流水线的架构师、DevOps,或者只是最近在社区刷到“slnx 要取代 sln”的消息想来确认一下,这篇文章应该都能给你一个清晰的判断。
1. 那个让人半信半疑的 .slnx 提交
1.1 第一次看到 .slnx 时的本能反应
我是从 .NET Framework 时代一路用过来的,早年写 ASP.NET WebForms、WinForms,后来转 .NET Core,再到现在天天写 .NET 8/9。Visual Studio 解决方案文件 .sln 在我眼里几乎和项目文件本身同等重要,甚至很多时候我根本不看里面的内容——项目结构、引用关系、构建配置、启动项,全靠它管着。
所以当我发现 Visual Studio 2022 17.13 开始把一种新的 .slnx 格式推到台前,而且微软官方明确表示这是“新解决方案格式”的时候,我第一反应是:能不能别折腾了?.sln 又没坏,为什么要换?这种情绪我相信很多人都有。它跟 C# 语言版本升级不一样,那是向下兼容、加新语法;这种格式层面的大动脉手术,搞不好会让整个团队、所有周边工具链全部重来一遍。
但把那个 .slnx 文件用记事本打开之后,我承认我愣了一下——里面不是我以为的一大坨 GUID 和配置块,而是一份清爽的 XML。结构一目了然,甚至不需要装任何工具就能看懂哪些项目在哪个文件夹里。那一刻我开始觉得,这个变化可能不是微软拍脑袋想出来的,而是真的在解决一个长期被人忍受的痛点。
1.2 这个文件本质上是给机器看的,不是给人看的
想要理解 .slnx 为什么要出现,得先承认一个事实:传统 .sln 文件从设计之初就不是给普通开发者手工编辑的,它更像一份给 Visual Studio 内部状态机读的序列化数据。
.sln 的发展史可以一直追溯到 Visual Studio 诞生初期。这些年它不断往里面塞东西,格式版本、VisualStudioVersion、MinimumVisualStudioVersion、项目 GUID、项目类型 GUID、解决方案配置平台、项目配置映射、嵌套关系、扩展性全局块……每加一个功能就往这个文本文件里加一个 Section。功能是加上了,但文件的信噪比越来越低。
对一个只有两三个项目的解决方案来说,.sln 可能还不算夸张;但如果你在那种动辄几十个项目、文件夹层级分明的企业级解决方案里待过,一定见过这种画面:只是在解决方案里把一个项目拖进另一个文件夹,git diff 里就多出十几二十行 NestedProjects 的 GUID 映射变化。这些改动没有一行业务价值,又特别容易在多人同时调整结构时制造合并冲突。
.slnx 想解决的就是这个问题。它把一个解决方案应该关心的信息收敛成“有哪些项目、放在什么文件夹层级、解决方案级别的配置”,把 IDE 自身的状态、窗口布局、用户级设置全部彻底踢出去。这些本来就该放在 .vs 或者 .suo 这类本地文件里,而不是跟着代码仓库所有人一起共享。
1.3 并不是说要立刻告别 .sln
这里先把结论放在前面,避免后面内容被误读:微软没有也不可能立刻干掉 .sln。至少在现在这个阶段,Visual Studio、MSBuild 依旧对老格式有完整的读写支持。.slnx 更像是生态向新标准迁移的第一步,而不是一道“明天必须全部转过去”的命令。
给团队成员升级完 VS 版本之后,我们继续用了相当长一段时间的混合状态——新项目用 .slnx,老项目继续保留 .sln,两边同时出现在仓库里,日子也完全过得下去。真正的摩擦往往不是格式本身,而是“你以为别人能打开,结果不能”这类协作问题。后面我会专门讲。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 旧格式的债,新格式在还
2.1 为什么 .sln 能让 diff 变得这么难看
如果你经历过一次“只调整了解决方案文件夹结构,却产生了几十行冲突”的代码评审,应该能理解我为什么格外在意 .slnx 在这方面的改进。
传统 .sln 里有两类信息极其容易制造噪音。一类是项目类型 GUID 和项目 GUID,它们是 Visual Studio 内部识别项目的钥匙,一旦某个项目的 GUID 因为重新生成而改变,整个文件里所有涉及该 GUID 的配置映射都要跟着变。另一类是解决方案文件夹的嵌套关系,.sln 用一堆 {ParentGuid} = {ChildGuid} 形式来表达层级,可读性约等于零。
比如下面这一段,是从一个小型 .sln 里截出来的典型片段:
code复制Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApp", "src\MyApp\MyApp.csproj", "{9E2A5C99-9F1B-4A93-8D8A-39253C76C342}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyLib", "src\MyLib\MyLib.csproj", "{12E4F4DC-091A-4C99-A8B9-2E2B77EF2D40}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E2A5C99-9F1B-4A93-8D8A-39253C76C342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E2A5C99-9F1B-4A93-8D8A-39253C76C342}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E2A5C99-9F1B-4A93-8D8A-39253C76C342}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E2A5C99-9F1B-4A93-8D8A-39253C76C342}.Release|Any CPU.Build.0 = Release|Any CPU
{12E4F4DC-091A-4C99-A8B9-2E2B77EF2D40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12E4F4DC-091A-4C99-A8B9-2E2B77EF2D40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12E4F4DC-091A-4C99-A8B9-2E2B77EF2D40}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12E4F4DC-091A-4C99-A8B9-2E2B77EF2D40}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
能一眼看懂这里面哪个项目归属于哪个文件夹吗?不能。这个文件里所有信息都由 GUID 串联,一旦项目数量过二十,人工追踪基本不可能。工具要解析它,也得照着这一大套格式写专用的状态机解析器,这也是为什么有些老牌自动化脚本遇到 .sln 时总会出些莫名其妙的 bug——它们多半在用自己写的正则硬撑。
2.2 .slnx 实际上长什么样
再看同样的两个项目放在 .slnx 里是什么效果:
xml复制<Solution>
<Folder Name="/src/">
<Project Path="src/MyApp/MyApp.csproj" />
<Project Path="src/MyLib/MyLib.csproj" />
</Folder>
</Solution>
对,就这几行。没有 GUID,没有版本号,没有纷繁复杂的 GlobalSection。项目路径是直接可读的相对路径,文件夹层级用 XML 嵌套来表达,结构是什么样,文件里就是什么样。
这个设计思路和现代 .csproj 的演进方向完全一致。还记得 SDK Style 的 .csproj 出来之前,一个项目文件动辄几百行,里面塞满 GUID、文件包含列表、编译目标。后来 SDK Style 项目把构建默认行为收进 Sdk 里,项目文件瘦身到几十行,于是我们终于敢手写 .csproj 了。.slnx 在解决方案层面又做了一次同样的事。
对于经常要用命令行操作解决方案的人,.slnx 带来的改变更直接。以前我想用脚本判断某个解决方案包含哪些项目,不管用什么语言写,都会陷入解析 .sln 的泥潭;现在只需要加载 XML,用标准库遍历 Solution 下的 Project 元素即可。它把解决方案文件从一个“私有状态格式”变成了“公开数据格式”。
2.3 为什么新格式选 XML 而不是 JSON
看到这里你可能想问:现在不是 JSON 更流行吗?为什么微软不用 .sln.json 之类的东西?
一个原因是整个 .NET 的基础构建体系——MSBuild——从项目文件到属性表,全线都是 XML。项目文件用 XML,解决方案文件再用回 XML,工具链可以在同一套基础设施上做语法高亮、Schema 校验和结构化处理;如果换成 JSON,那就要在 MSBuild 里再维护一套全然不同的解析管道,纯粹是给自己找不痛快。
还有一个比较微妙但又实际的原因:XML 支持注释。团队里总有一些约定俗成的说明,比如“这个项目不能删除,发布流水线里有硬依赖”或者“这个文件夹对应的是某个外部模块”,这些内容写进 .slnx 里作为注释,是很自然的协作方式。JSON 虽然也允许注释,但大多数团队为了严格的 JSON schema 一般都不会在配置里放注释,视觉上也更费劲。
其实对我们终端用户来说,真正重要的不是选 XML 还是 JSON,而是这个格式终于可以被机器解析了。标准 XML 解析器遍地都是,.slnx 不再需要专门的私有解析逻辑。这意味着以后任何语言、任何工具都能轻松读取解决方案结构,这才是它最大的价值。
3. 第一次把项目迁移到 .slnx
3.1 迁移前,先把环境条件确认清楚
我在自己负责的某个中大型解决方案上做了一次完整迁移,过程中犯过一个比较低级的错误,这里写出来给大家提个醒:迁移前一定要先确认所有会接触这个仓库的人,工具版本到底到哪了。
.slnx 不是那种“老版本 VS 也能凑合打开”的格式。Visual Studio 2022 的 17.13 版本才开始真正支持,更早的版本直接双击 .slnx 会提示无法识别。所以我在做迁移之前,第一件事就是去问团队和运维那边:所有人是不是都已经用上了支持 .slnx 的 VS 版本?CI 里用的 dotnet SDK / VS Build Tools 镜像是不是也已经够新?
确认没问题之后,还要看一眼这个解决方案里有没有什么“非主流”内容。比如有些解决方案会在 Solution Items 里放一堆部署脚本、架构文档,或者用解决方案级别的构建依赖去管理项目生成顺序。这些在 .slnx 迁过去之后不一定原样保留,尤其是一些古老的“解决方案文件夹承载文档”的用法,建议迁移前先决定好这些文件的归宿。
3.2 通过命令行迁移的基本操作
命令行是我个人最推荐的方式,因为它可重复、可审计,以后写进团队文档也更方便。
先确认当前 SDK 版本:
bash复制dotnet --version
如果你的 SDK 是 .NET 9.0.2xx 或更高版本,那么 dotnet CLI 已经能识别 .slnx 这种扩展名。下面是把一个已有 .sln 转成 .slnx 的命令:
bash复制dotnet sln MyApplication.sln migrate
执行完这条命令之后,目录下会出现一个同名但扩展名为 .slnx 的文件。如果命令执行过程中遇到“当前 SDK 不支持”这类错误,有三种可能:一是 SDK 版本确实太老,需要升级;二是命令名称在不同 SDK 里可能有差异,具体可以用 dotnet sln --help 查看;三是这个命令在部分预览版里还不稳定。
如果 migrate 子命令不可用,也不用慌,还有一个更朴素但可靠的办法:用新格式重新生成解决方案文件,再手动把项目一个个加进去。这个过程不依赖迁移命令,只要 CLI 能识别 .slnx 就能用:
bash复制dotnet new sln -n MyApplication --format slnx
dotnet sln MyApplication.slnx add src/MyApp/MyApp.csproj src/MyLib/MyLib.csproj
项目数量少的时候,手写命令完全能接受。项目数量多的时候,我会写一段脚本去读取旧 .sln 里的项目路径列表,然后批量执行 dotnet sln xxx.slnx add。不过这种情况还是建议先用 migrate,真要到了手写批量脚本那一步,说明这个解决方案的复杂程度已经很高了,迁移前需要更谨慎。
3.3 如果你更习惯 Visual Studio 界面
如果你不只是“能用命令行”,而是每天在 Visual Studio 里完成绝大多数开发,那也可以完全通过界面完成迁移。在支持 .slnx 的版本里,用 VS 打开旧的 .sln 之后,可以通过“另存为”方式把解决方案保存为 .slnx 格式。保存完之后 VS 当前会话会自动切到新格式上,后面继续增删项目、调整文件夹结构,都会直接写到 .slnx 上。
第一次通过界面保存 .slnx 之后,强烈建议立刻关掉 VS,到 git 里看一眼文件 diff,而不是直接把整个 .sln 删掉。因为我遇到过 VS 在转换时会顺手调整一些缩进和换行,看起来“凭空”多出很多 diff;这些不影响功能,但会影响评审观感。看清楚之后再提交,可以避免很多不必要的争论。
3.4 迁移完成后要检查的几件事
格式转换不等于项目结构转换,有些东西必须人工确认。
第一,文件夹层级。老 .sln 里如果用了很多嵌套的解决方案文件夹,迁移后一定要在 VS 里展开确认层级没有错乱。我见过一次迁移后所有项目平铺在根节点的情况,虽然不影响编译,但那种“项目列表一夜回到解放前”的感觉,对开发者来说相当致命。
第二,启动项目配置。.slnx 不会保存这台机器上“当前指定哪个项目为启动项目”这类用户偏好。如果你平时依赖“多启动项目”来联调多个服务,迁移后需要在 VS 里重新设置一遍。这不是格式的 bug,而是新版格式刻意把用户级配置和仓库级配置分离的结果。
第三,项目生成顺序和依赖关系。如果有些项目之间没有写 ProjectReference,而是靠构建顺序在硬撑着,那这些依赖关系很可能在 .slnx 里体现不出来。建议这类项目趁迁移的机会,把依赖关系补成正规的 ProjectReference,这种健壮性对以后换构建系统也有好处。
第四,全局配置项。如果旧 .sln 里有一些通过 GlobalSection(ExtensibilityGlobals) 或在 SolutionProperties 里做的自定义配置,这些内容迁到 .slnx 后可能需要手动补。大多数个人项目根本用不到这些东西,但那些深度定制过 Visual Studio 解决方案行为的团队要留意。
4. 从一笔提交炸掉 CI 开始:迁移后的排查过程
4.1 现象:CI 在第一分钟就红了
把 .slnx 提交进去的当天,CI 就挂了。我的第一个反应是“难道迁移格式本身有坑?”,点开流水线日志一看,报错信息非常直白:
code复制MSB1009: Project file does not exist.
这个报错指向的文件名还是老的 MyApplication.sln。问题很清楚,不是格式转换失败,而是 CI 的 workflow 里写死了要构建 .sln,仓库里的 .sln 一删,自然就找不到文件了。
这个坑看起来非常简单,但它很容易被忽略:.slnx 迁移牵涉的不只是 Visual Studio,还包括所有 dotnet 命令、构建脚本、测试发现工具、代码覆盖率插件和部署流程。任何一处写着 .sln 的硬编码,都会在文件改名后瞬间暴露出来。
4.2 从日志反推:哪些地方引用了旧文件名
我当时没有急着只改 CI 里的那一个文件,而是在仓库里做了一个全局搜索,把所有引用 .sln 的地方都拉了出来,挨个过一遍。搜索清单大致包括:
- GitHub Actions / Azure Pipelines 等 CI 配置文件里的
dotnet build xxx.sln - 本地开发脚本,比如 build.ps1、build.sh 里的解决方案路径
- 解决方案级测试命令,比如
dotnet test xxx.sln - 文档里写的“快速开始”步骤
- 生成代码、数据库迁移工具、代码分析脚本里对解决方案文件路径的硬引用
- 某些静态代码分析工具,它们会基于解决方案文件递归检查项目
逐个排查完之后,我把 CI 配置文件里的构建命令改成了:
bash复制dotnet build MyApplication.slnx
并顺手把测试脚本、本地一键构建脚本都改成了 .slnx。这次的教训是:格式迁移不是只改一个文件扩展名那么简单的切换,而是一次“全链路字符串替换+验证”工程。
4.3 第二个坑:同事的旧 VS 打不开新格式
CI 跑通之后,问题并没有结束。几天后,团队里一个同事在群里说:拉完最新代码,双击解决方案文件打不开,VS 提示“此版本的 Visual Studio 不支持此项目类型”,更准确地说是不支持 .slnx 扩展名。
我让他先敲 devenv /version 看了下版本,果不其然,还是 Visual Studio 2022 17.11。17.13 不是自动升级的,很多企业环境里 VS 还是几个月前安装的版本,根本不在预装更新范围之内。
这个问题的排查链路不复杂:确认现象 → 查看版本号 → 对照支持矩阵 → 升级工具。
但要说解决方案里的坑,并不在升级本身,而是在“升级之前项目怎么办”。我们当时的做法是:先拉一个和 .slnx 完全等效的 .sln 临时文件,让旧版 VS 的同事继续干活;等他们腾出时间升级完 VS,再彻底删掉临时 .sln。这样做虽然会让仓库里短暂出现两份解决方案文件,但双格式共存总比让人卡在原地强。
后来我意识到,这也是很多企业团队短期内最现实的过渡方案:.slnx 作为事实标准入库,老格式作为兼容副本在过渡期保留。前提是约定好:每次项目结构变更后,两份文件都要保持同步,否则又会出现双头管理的问题。
4.4 双格式共存导致的另一场混乱
双格式方案用了两个星期,第二个麻烦来了。一位同事在 VS 里正常往 .slnx 里加了一个新项目,但完全忘了更新仓库里那个过渡用的 .sln。结果另一个一直用旧 VS 的同事编译老 .sln 时发现新项目根本没进编译,又排查了半天。
这事本质上不是格式的问题,而是流程纪律问题。后来我们在仓库根目录加了一个 README 说明,明确写了“过渡期间,如果你用新版 VS,请只编辑 .slnx;每次提交前,请运行转换脚本把 .slnx 同步成 .sln”。又写了一个简单的本地脚本,每次 git commit 之前钩住,检查两份文件是否真的对应同一个项目集合。这才把混乱按下去。
所以我的建议是:如果团队里还有人没升级到 17.13+,要么等所有人升级完再统一迁,要么就做好同步脚本。最忌讳的是既不统一版本,又没有同步机制,让开发者在两种格式之间反复手动作业。
5. 生态支持梳理:谁已经站到 .slnx 这边
我在做迁移调研时,把相关工具梳理了一张表,这里按我实际验证过的情况列出来,方便大家对照自己的工具链:
| 工具 / 环境 | 对 .slnx 的支持 |
我的实际验证/备注 |
|---|---|---|
| Visual Studio 2022 17.13+ | 原生支持 | 这是使用 .slnx 的基础门槛 |
| 更早版本的 Visual Studio | 不支持 | 只能打开 .sln,需升级 |
| Visual Studio Code + C# Dev Kit | 支持中 | 更新到最新 C# Dev Kit 插件后可用,建议保持插件自动更新 |
| .NET SDK(dotnet CLI 9.0.2xx 及以后) | 支持创建/解析/部分迁移 | 建议用最新 SDK 再跑迁移,错误信息更完善 |
| JetBrains Rider | 持续跟进支持 | 关注 Rider 更新日志,测试版往往更快支持新格式 |
| GitHub Actions / Azure Pipelines | 取决于镜像版本 | 只要镜像里的 VS/SDK 足够新,直接改 .slnx 路径即可 |
| 各种旧版构建脚本/自动化工具 | 需要逐个验证 | 搜索仓库里写在 .sln 的地方,逐项替换 |
| 代码分析、测试覆盖率、NuGet 相关第三方插件 | 参差不齐 | 我这里至少测到过两个工具暂不支持 .slnx,只能临时给它们喂 .sln 文件 |
真正要留意的不是大厂的 IDE,而是那些你已经深度依赖的第三方小工具。它们解析 .sln 往往用的是自己写的一套老逻辑,在没有主动适配 .slnx 之前,你只能给它们保留一个兼容副本,或者在仓库里用脚本在构建前自动把 .slnx 转成临时 .sln 喂给它们。
这种“给老工具留一条退路”的思路,在我自己的实践里非常有效。等工具链全都跟上之后,再把临时兼容层删掉,整个过程不会阻塞主线开发。
6. 要不要赶这一波:我的决策框架
6.1 先说结论:什么时候应该直接用 .slnx
如果你满足下面这些条件,我倾向于直接上手 .slnx,不用犹豫:
- 你是新建项目,团队里所有开发者的 Visual Studio 都已经在 17.13 以上;
- 你的 CI 可以方便地更换镜像版本,不依赖某台老旧的构建机;
- 解决方案本身不复杂,没有一堆依赖 Visual Studio 私有扩展点的自定义功能;
- 团队里大多数人是用命令行或 VS Code 做开发,而不是重度依赖老 VS 的某些特殊窗口功能。
我在自己负责的几个新项目里就直接选用了 .slnx,日常体感相当不错。最明显的变化是代码评审变轻松了。以前评审里看到 .sln 一大片改动,我总是心悬着,怕有人顺手把某个项目的 GUID 弄坏;现在 .slnx 里加项目就是加几行 XML,删项目就是删一个 <Project> 标签,安全性高了很多。
6.2 什么时候先按兵不动
反过来,如果下面任何一条戳中你,我的建议是先别急着迁:
| 信号 | 潜在风险 |
|---|---|
| 团队里还有人用 VS 2022 17.12 或更低版本 | 他们打不开 .slnx |
| CI 用的是老镜像,不方便升级 SDK 或 VS Build Tools | 构建命令可能直接挂在格式识别上 |
| 解决方案里依赖某些第三方扩展的解决方案级功能 | 第三方扩展大概率还没适配 .slnx |
仓库里有很多自动化脚本硬编码了 .sln 路径 |
需要逐个排查替换,工程量大 |
| 你只是“想赶时髦”,项目马上要发版 | 不应当在发布窗口期引入这种基础设施变更 |
这种时候最理性的做法是:让新项目先跑在 .slnx 上积累经验,老项目继续用 .sln,等地基都打好了再统一推进。基础设施的迁移最怕的不是慢,而是明明条件不成熟还要强行切换,最后让整个团队给工具链升级买单。
6.3 如何一步步平滑过渡,而不是一刀切
如果决定要迁,我建议不要在大版本发布前的一两周突然提交一个“删掉 .sln,换成 .slnx”的大 PR,而是分四步慢慢走。
第一步,先用支持新格式的 VS / CLI 打开现有 .sln,在本地生成一份 .slnx,观察里面的 XML 是否符合预期,构建、测试全部跑一遍。
第二步,让团队里两个熟悉命令行的人先切到 .slnx 上工作几天,看有没有隐藏问题。这个阶段仓库里还是以 .sln 为准,.slnx 只存在于他们本地。
第三步,把 .slnx 提交进仓库,但暂时保留 .sln。CI 换成构建 .slnx,本地脚本也切过去。旧 .sln 只作为一个兼容备份留在仓库,等所有人确认没问题以后再单独提一个 commit 删掉。
第四步,删除 .sln 后,立刻在仓库里搜一遍有没有遗漏的 .sln 引用。这一步我上面说过,全链路排查,尤其是文档里的快速开始命令。
最后再分享一个实用的小技巧。如果团队决定全面切到 .slnx,记得在仓库根目录的 .gitattributes 里加上这一行:
gitattributes复制*.slnx text eol=crlf
原因很简单:虽然 XML 本身对换行风格不敏感,但 Visual Studio 在 Windows 下保存文件时默认倾向 CRLF,如果让不同平台上的开发者各自按本机风格提交,git 会产生一些无意义的换行噪音。提前用 .gitattributes 锁定换行规则,能省掉很多“为什么这个文件每次都有 diff”的争论。
从我个人目前的实践来看,.slnx 不会让用了二十多年的 .sln 一夜之间消失,但它的确正在成为 .NET 工具链新一轮演进的事实标准。我自己的感受是,与其等到生态全部倒逼过来再被动适应,不如趁现在项目结构还能掌控的时候主动试一把——尤其是新项目,直接用 .slnx 几乎没有成本。至于那些承载了大量历史包袱的老解决方案,慢慢来,不丢人。
