解决方案组成与分层架构
WattToolkit(Steam++)仓库使用单一 XML 格式解决方案文件 WattToolkit.slnx 组织全部源代码,通过 7 个编号解决方案文件夹(/0.Root ~ /6.Tools)实现「根配置 → 宿主 → 参考程序集 → 测试 → 共享库 → 插件 → 工具」的分层组织,并由 src/Directory.Build.props 将编译属性、共享 AssemblyInfo 与隐式 global using 统一注入到解决方案内的每一个项目。
Purpose and Scope
本页是仓库顶层结构的权威参考,覆盖以下内容:
WattToolkit.slnx解决方案的完整组成:解决方案文件夹、项目清单、目标平台(Any CPU / ARM / ARM64 / x64 / x86);- 分层架构与各层职责:
/1.AppHost宿主层、/4.Shared共享层(含Avalonia.Ref与ClientSDK子层)、/5.Plugins插件层、/2.Reference参考程序集层(git 子模块)、/3.Test测试层、/6.Tools工具层; - 由
src/Directory.Build.props、src/TFM_NETX*.props与src/ImplicitUsings.*.cs构成的统一构建约定与「配置注入」机制; src/README.md中记录的命名空间 / 文件夹约定(v3.X 时代沿用至今的分层语义)。
本页不覆盖(留给兄弟页面):各插件(Accelerator、Authenticator、ArchiSteamFarmPlus 等)的内部实现、Avalonia UI 层与视图模型细节、IPC 通信机制、反代加速实现、数据库实体设计等。本页只回答「解决方案由什么组成、如何分层、构建配置如何统一注入」。
Overview
解决方案文件:WattToolkit.slnx
仓库没有使用传统 .sln 文本格式,而是采用新的 XML 解决方案格式 .slnx。文件以 <Solution> 为根节点,先声明 5 个目标平台,再以嵌套 <Folder> / <Project> / <File> 节点描述整个目录树,最后在文件夹结构之外声明启动项目 src/BD.WTTS.Client.Avalonia.App:
1<Solution>
2 <Configurations>
3 <Platform Name="Any CPU" />
4 <Platform Name="ARM" />
5 <Platform Name="ARM64" />
6 <Platform Name="x64" />
7 <Platform Name="x86" />
8 </Configurations>
9 ...
10 <Project Path="src/BD.WTTS.Client.Avalonia.App/BD.WTTS.Client.Avalonia.App.csproj" />
11</Solution>Source: WattToolkit.slnx
选择 .slnx 的设计意图在于:XML 格式对合并冲突更友好、可被工具直接解析,并且天然支持「编号前缀文件夹」这种显式分层表达——文件夹编号即依赖方向(0 是被所有人依赖的配置层,1.AppHost 依赖 4.Shared,4.Shared 依赖 2.Reference)。
关键概念与术语
| 术语 | 含义 |
|---|---|
| 解决方案文件夹(Solution Folder) | .slnx 中的逻辑分组(如 /5.Plugins/),不要求物理路径一致,仅用于在 IDE 中表达分层 |
| AppHost(宿主) | 桌面应用宿主进程相关项目,负责进程模型与启动桥接 |
参考程序集层(ref/) | 通过 .gitmodules 引入的第三方 / 自维护 fork(git 子模块),以源码形式参与编译 |
Avalonia.Ref | 通过友元程序集或空程序集实现手动裁剪(trimming)的 Avalonia 兼容项目集 |
ClientSDK | 客户端调用云端微服务的 SDK 项目集(Models / ViewModels / Resources / Primitives) |
| 插件(Plugins) | 按业务域拆分的功能模块(加速器、令牌验证器、挂卡等),编译期即集成进客户端 |
ImplicitUsings.*.cs | 按域拆分的隐式 global using 文件,通过 MSBuild Compile 项注入到各项目 |
| CPM(Central Package Management) | ManagePackageVersionsCentrally=true,NuGet 包版本统一由 Directory.Packages.props 管理 |
Architecture
下图展示解决方案的整体分层组成。图中实线表示「上层依赖下层」的分层方向(该方向遵循 src/README.md 记录的历史分层语义,具体项目间的 ProjectReference 以各 csproj 为准);虚线表示根配置层对全部项目的属性注入关系(由 src/Directory.Build.props 实现,见后文)。
各层职责说明:
/0.Root根配置层:不产出程序集,而是承载 CI 工作流(.github/workflows/CI.yml)、nuget.config、.gitmodules、集中包版本(ref/DirectoryPackages/Directory.Packages.props)、src/.editorconfig、src/Directory.Build.props,以及Source/(共享AssemblyInfo*.cs、Utils.cs)、Source/ImplicitUsings/(31 个按域拆分的隐式 using 文件)、TFM/(6 个目标框架组合属性文件)与Document/(含doc/program-file-structure/下 Linux/macOS/Windows 三平台程序文件结构文档)。/1.AppHost宿主层:BD.WTTS.Client.AppHost与BD.WTTS.Client.AppHost.Bridge(注意:该项目文件名为Steam++.csproj,属于历史命名遗留)。启动项目BD.WTTS.Client.Avalonia.App登记在文件夹结构之外。/2.Reference参考程序集层:全部位于ref/下并以 git 子模块形式引入,分 6 组:AppCenter(崩溃/分析上报)、Avalonia(图像解码扩展Avalonia.Gif、LibAPNG)、Common(BD.Common*15 个基础类库:Essentials、Primitives、Mvvm(.ReactiveUI)、Pinyin(.TinyPinyin)、Security、Settings、Repositories.SQLitePCL、Area 等)、Ipc(dotnetCampus.Ipc+ Analyzers)、Steam(BD.SteamClient、BD.SteamClient.Models.Protobuf、Facepunch.Steamworks.Posix/Win64、Steam4NET、Gameloop.Vdf、ValveKeyValue)、WinAuth(令牌验证算法)。/3.Test测试层:单一单元测试项目BD.WTTS.UnitTest。/4.Shared共享层:客户端核心BD.WTTS.Client、Avalonia View 层BD.WTTS.Client.Avalonia、进程间通信BD.WTTS.Client.IPC、图像兼容BD.Avalonia8.Image2.Compat、共享代码项目OSShuttingDownHelper.shproj(.shproj直接以源码形式共享编译项),以及两个子层:Avalonia.Ref(10 个项目:Avalonia.Base(.Internals)、Avalonia.Controls.Internals、Avalonia.Desktop、Avalonia.Diagnostics、Avalonia.Native、Avalonia.Skia.Internals、Avalonia.WebView2、Avalonia.Win32、Avalonia.X11)与ClientSDK(BD.WTTS.MicroServices.ClientSDK、BD.WTTS.MicroServices.Primitives(.Models/.ViewModels/.Resources)、BD.WTTS.Primitives(.Models/.ViewModels)、BD.WTTS.Primitives.Resources)。/5.Plugins插件层:8 个业务插件项目——Accelerator(网络加速)、Accelerator.ReverseProxy(反向代理实现)、ArchiSteamFarmPlus(ASF 挂卡)、Authenticator(令牌验证器)、GameAccount(账号切换)、GameList(游戏库存)、GameTools(游戏工具)、SteamIdleCard(挂卡)。/6.Tools工具层:构建/开发期工具——BD.Common.Settings.V4.SourceGenerator.Tools(设置源生成器工具)、BD.WTTS.Client.Avalonia.Designer.HostApp(设计器宿主)、BD.WTTS.Client.Tools.HostsTest、BD.WTTS.Client.Tools.OpenSourceLibraryList(开源许可清单生成)、BD.WTTS.Client.Tools.Publish(发布工具)。
核心机制:统一构建约定(src/Directory.Build.props)
src/Directory.Build.props 是分层架构中「配置即代码」的关键机制。MSBuild 会沿目录树向上查找该文件并自动应用到 src/ 下所有项目,从而让 40+ 个项目共享同一套编译语义,无需在每个 csproj 重复配置。
1<Project>
2 <PropertyGroup>
3 <DotNet_Version>11.0</DotNet_Version>
4 <NoWarn>$(NoWarn);NU1507;1591;SA1612;IL2026;IL2091</NoWarn>
5 <LangVersion>latest</LangVersion>
6 <Nullable>enable</Nullable>
7 <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
8 <GenerateDocumentationFile>false</GenerateDocumentationFile>
9 <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
10 <ImplicitUsings>enable</ImplicitUsings>
11 <IsTrimmable>true</IsTrimmable>
12 ...
13 <Deterministic>true</Deterministic>
14 <CETCompat>false</CETCompat>
15 </PropertyGroup>
16</Project>Source: Directory.Build.props
关键属性的设计意图:
Nullable=enable+LangVersion=latest:全解决方案启用可空引用类型检查与最新语言特性,配合ImplicitUsings=enable消除样板 using;ManagePackageVersionsCentrally=true:启用 CPM,所有 NuGet 包版本集中管理在ref/DirectoryPackages/Directory.Packages.props(登记于.slnx的/0.Root文件夹),避免多项目版本漂移;IsTrimmable=true+NoWarn中的IL2026;IL2091:客户端需要 AOT/裁剪发布(对应TFM_NETX*.props的多 TFM 矩阵),故声明程序集可裁剪,同时抑制裁剪警告以便逐步治理;- 关闭
GenerateAssemblyTitleAttribute等 9 项程序集特性生成:因为程序集信息由/0.Root/Source/下共享的AssemblyInfo.cs、AssemblyInfo.Constants.cs、AssemblyInfo.Version.Max.cs统一提供,避免双重定义。
共享源码注入
该文件还把根级源码文件以 Compile 项形式注入到每个项目,并通过 LinkBase=Properties 在 IDE 中归组:
1<ItemGroup>
2 <Compile Include="..\AssemblyInfo.cs">
3 <LinkBase>Properties</LinkBase>
4 </Compile>
5 <Compile Include="..\ImplicitUsings.BCL.cs">
6 <LinkBase>Properties</LinkBase>
7 </Compile>
8 <Compile Include="..\ImplicitUsings.Common.cs">
9 <LinkBase>Properties</LinkBase>
10 </Compile>
11</ItemGroup>Source: Directory.Build.props
.slnx 的 /0.Root/Source/ImplicitUsings/ 文件夹中登记了 31 个 ImplicitUsings.*.cs 文件(ArchiSteamFarm、AspNetCore、AutoMapper、Avalonia、BCL、Common、Controllers、Data、EntityFrameworkCore、Identity、Jobs、JsonProperty、JWT、MessagePack、Models、MSEX、Nito、NLog、Plugins、Quartz、ReactiveUI、Repositories、Services、Settings、SQLite、Steam、UI、UI.ViewModels、UI.Views、UnitTest、WTTS)。这套设计让「按域组织的 global using」成为全局分层的一部分:任何项目引用到某一域(如 Services、Repositories、Steam)时无需手写 using。
目标框架矩阵(TFM props)
/0.Root/TFM/ 提供了 6 个目标框架组合文件,供不同项目按需导入以组成多目标矩阵:TFM_NETX.props、TFM_NETX_SINGLE.props、TFM_NETX_WINDOWS.props、TFM_NETX_WITH_ALL.props、TFM_NETX_WITH_DESKTOP.props、TFM_NETX_WITH_WINDOWS.props。这与 .slnx 中的 5 个平台(Any CPU、ARM、ARM64、x64、x86)共同支撑跨平台发布矩阵。此外 Directory.Build.props 对 net11.0 追加了 runtime-async=on 特性开关。
解决方案项目清单
下表汇总 .slnx 中登记的全部项目及其分层归属(共 41 个项目 + 1 个 .shproj):
| 解决方案文件夹 | 项目 | 职责 |
|---|---|---|
| /1.AppHost | BD.WTTS.Client.AppHost | 桌面客户端宿主进程 |
| /1.AppHost | BD.WTTS.Client.AppHost.Bridge(Steam++.csproj) | 宿主桥接(历史命名) |
| (根) | BD.WTTS.Client.Avalonia.App | 启动项目(Avalonia 桌面应用) |
| /2.Reference/AppCenter | BD.AppCenter.Any、BD.AppCenter.Analytics.Any | 崩溃与分析上报 SDK fork |
| /2.Reference/Avalonia | Avalonia.Gif、LibAPNG | GIF/APNG 图像解码扩展 |
| /2.Reference/Common | BD.Common + 14 个 BD.Common.* | 通用基础类库(Essentials/Primitives/Mvvm/Pinyin/Security/Settings/Repositories 等) |
| /2.Reference/Ipc | dotnetCampus.Ipc + dotnetCampus.Ipc.Analyzers | IPC 通信与代码分析器 |
| /2.Reference/Steam | BD.SteamClient、BD.SteamClient.Models.Protobuf、Facepunch.Steamworks.Posix/.Win64、Steam4NET、Gameloop.Vdf、ValveKeyValue | Steam 互操作与 VDF/protobuf 解析 |
| /2.Reference/WinAuth | WinAuth | 令牌验证算法 |
| /3.Test | BD.WTTS.UnitTest | 单元测试 |
| /4.Shared | BD.WTTS.Client | 客户端核心类库 |
| /4.Shared | BD.WTTS.Client.Avalonia | Avalonia View 层 |
| /4.Shared | BD.WTTS.Client.IPC | 客户端 IPC |
| /4.Shared | BD.Avalonia8.Image2.Compat | Avalonia 8 图像兼容层 |
| /4.Shared | OSShuttingDownHelper.shproj | 共享编译项(关机辅助) |
| /4.Shared/Avalonia.Ref | Avalonia.Base(.Internals) 等 10 个项目 | 通过友元程序集/空程序集手动裁剪 |
| /4.Shared/ClientSDK | BD.WTTS.MicroServices.ClientSDK 等 9 个项目 | 云端微服务客户端 SDK |
| /5.Plugins | Accelerator、Accelerator.ReverseProxy、ArchiSteamFarmPlus、Authenticator、GameAccount、GameList、GameTools、SteamIdleCard | 8 个业务功能插件 |
| /6.Tools | Settings.V4.SourceGenerator.Tools、Avalonia.Designer.HostApp、Tools.HostsTest、Tools.OpenSourceLibraryList、Tools.Publish | 构建期与开发期工具 |
启动与加载流程(编译期视角)
从解决方案结构看,一次典型的桌面客户端启动在编译期表现为以下依赖传播顺序:
这一顺序解释了分层的设计动机:插件与 UI 都只依赖核心类库 BD.WTTS.Client,而所有对第三方 / 子模块的依赖收口在核心层与参考程序集层。新增一个插件时,只需在 /5.Plugins 增加一个项目并引用核心层,即可自动继承全部构建约定,不会触碰上层宿主代码。
历史分层语义(src/README.md)
src/README.md 记录了 v3.X 时代(当时的 ST.* 命名)的项目结构约定。虽然命名已演进为 BD.WTTS.*,其中描述的分层职责仍与当前 .slnx 结构一一对应,是理解该仓库分层的重要文档:
1- Lib 类库
2 - ST 业务通用类库
3 - ST.Client 客户端通用类库
4 - Platforms
5 - ST.Client.Windows 用于 Windows 的实现
6 - ST.Client.Mac 用于 macOS 的实现
7 - ST.Client.Linux 用于 GNU/Linux 的实现
8 - UI Framework
9 - ST.Client.Avalonia 使用 Avalonia 实现的 View 层
10 - Avalonia.Ref 通过友元程序集调用内部函数或空程序集实现手动裁剪
11 - Web API
12 - ST.Services.CloudService 客户端调用服务端 API 定义Source: README.md
该文档同时记录了「命名空间/文件夹」约定,例如 Properties 下放置 AssemblyInfo.cs、InternalsVisibleTo.cs 与本地化资源 SR;Application 下按 Columns(模型实体列定义接口)、Converters(VM→V 值转换器)、Data(EFCore DbContext)、Entities(ORM 表实体)等子目录组织业务代码。.slnx 根文件夹对 src/AssemblyInfo*.cs 与 src/ImplicitUsings/* 的集中登记,正是这一约定在构建层的落地。
命名规范与演进
- 前缀分层:
BD.Common*(基础层)→BD.WTTS.MicroServices*/BD.WTTS.Primitives*(云 SDK 层)→BD.WTTS.Client*(客户端层)。前缀即命名空间层级,与解决方案文件夹编号对应。 - 历史遗留:
BD.WTTS.Client.AppHost.Bridge的项目文件仍名为Steam++.csproj;src/README.md中的ST.*命名是 v3.X 的旧称,文档开头以~~删除线~~标记已废弃项(如ST.Client.WPF、ST.Client.WinUI、ST.Tools.MinifyStaticSites等)。 - 特殊项目类型:
OSShuttingDownHelper.shproj使用共享项目(Shared Project)形式,向引用方直接贡献源码而非程序集引用——这是在多 TFM 下共享平台特定代码的常用手段。
Failure Modes、边界与运维注意
- 子模块拉取失败:
/2.Reference全部来自ref/下的 git 子模块(由/0.Root中的.gitmodules登记)。克隆仓库后若未执行git submodule update --init,MSBuild 将报找不到ref/Common/src/BD.Common/BD.Common.csproj等项目文件——解决方案无法加载。 - 集中包版本缺失:CPM 依赖
/0.Root登记的ref/DirectoryPackages/Directory.Packages.props。若该文件或其所在子模块缺失,NuGet 还原阶段即失败(NU1507相关警告已在NoWarn中豁免多 TFM 包版本不一致告警)。 - TFM 矩阵不一致:各项目通过导入不同
TFM_NETX*.props组成目标框架集合,如果某项目导入的组合与依赖项目不兼容(例如依赖方不带-windows后缀 TFM),还原阶段会报ValidateExecutableReferencesMatchSelfContained/TFM 不匹配错误。仓库将该属性显式置为false以放宽自包含发布校验。 - 程序集特性冲突:由于
Directory.Build.props注入了共享AssemblyInfo.cs,任何项目若再启用程序集特性生成或自建AssemblyInfo.cs会产生重复定义编译错误——这就是为什么该文件显式关闭了 9 项GenerateAssembly*Attribute。 - Avalonia.Ref 的裁剪脆弱性:
Avalonia.Ref通过友元程序集访问 Avalonia 内部类型或以空程序集替代,属于对上游内部实现的强耦合。升级 Avalonia 版本时该子层需要优先验证。
Extension Points
- 新增业务功能:在
/5.Plugins/下新建BD.WTTS.Client.Plugins.<Name>项目,引用BD.WTTS.Client即可。构建约定、隐式 using、可空检查与裁剪支持会通过Directory.Build.props自动生效,无需修改任何根配置。 - 新增按域隐式 using:在
src/下增加ImplicitUsings.<Domain>.cs,并在.slnx的/0.Root/Source/ImplicitUsings/文件夹登记,必要时在Directory.Build.props的Compile项组中追加注入。 - 新增跨平台 TFM 组合:在
/0.Root/TFM/增加新的TFM_*.props并在目标项目导入,.slnx的Configurations平台列表无需变更。 - 调整全局编译语义:所有对
Nullable、IsTrimmable、警告抑制、源链接(Microsoft.SourceLink.GitHub)的调整都应发生在src/Directory.Build.props,而不是散落到各 csproj。
Related Links
- 源码:WattToolkit.slnx — 解决方案完整组成
- 源码:Directory.Build.props — 统一构建约定
- 源码:src/README.md — 项目结构与命名空间约定
- 文档:doc/file-system.md、doc/program-file-structure/Windows.md — 运行期文件系统与三平台程序文件结构
- 相关 Wiki 主题:各插件实现(Accelerator、Authenticator 等)、IPC 架构、Avalonia View 层——见对应兄弟页面