.NET 10 WPF 推荐技术栈闭环¶
- 归档日期:2026-08-25
- 问题:在选择
.NET 10 LTS + WPF + CommunityToolkit.Mvvm、按需接入 Windows App SDK,并以 .NET 10 内置 WPF Fluent Theme 建立设计规范的前提下,列出推荐的所有技术栈并形成闭环。 - 默认产品:长期维护的 Windows 企业、工业、工具型或商业桌面应用。
总体结论¶
推荐基线:
Windows 11 + Visual Studio 2026 + .NET 10 LTS + C# 14
WPF + 内置 Fluent Theme + 自定义 Design Tokens
CommunityToolkit.Mvvm
Microsoft.Extensions.Hosting / DI / Configuration / Options / Logging
System.Text.Json + HttpClientFactory + Microsoft.Extensions.Http.Resilience
EF Core 10 + SQLite(单机)
或 ASP.NET Core 10 API + EF Core 10 + SQL Server/Azure SQL(多用户)
Windows App SDK / CsWin32 / WebView2(按需)
MSTest + Microsoft.Testing.Platform
Git + EditorConfig + Central Package Management + NuGet Audit
GitHub Actions 或 Azure Pipelines
MSIX + 代码签名 + 分阶段更新
结构化日志 + OpenTelemetry + Azure Monitor(按隐私要求启用)
这里的“闭环”是:需求、设计、开发、测试、构建、签名、发布、更新、监控和用户反馈能够回到下一轮需求,而不是只完成本地开发。
flowchart LR
A[需求与验收标准] --> B[原型与架构决策]
B --> C[纵向功能开发]
C --> D[单元/集成/UI/可访问性测试]
D --> E[PR 与 CI 质量门禁]
E --> F[版本化、签名、打包]
F --> G[试点环发布]
G --> H[日志、遥测、崩溃与更新监控]
H --> I[用户反馈与缺陷分级]
I --> A
一、技术栈总表¶
| 层级 | 默认推荐 | 状态 | 作用 |
|---|---|---|---|
| 操作系统 | Windows 11 x64;按需测试 ARM64 | 必选 | 开发、调试和目标平台 |
| IDE | Visual Studio 2026 | 必选 | .NET 10、C# 14、WPF Designer、调试、分析与发布 |
| SDK | 最新稳定版 .NET 10 LTS;global.json 禁止 Preview |
必选 | 统一开发机和 CI 工具链 |
| 语言 | C# 14,Nullable 开启 | 必选 | 主开发语言和空值安全 |
| UI 框架 | WPF | 必选 | Windows 桌面 UI |
| 基础主题 | .NET 10 内置 WPF Fluent Theme | 必选 | Windows 11 风格基础控件和亮暗主题 |
| 设计系统 | 语义颜色、Typography、4 epx Spacing、Geometry、Icons、组件状态 | 必选 | 保证全局一致和可维护 |
| MVVM | CommunityToolkit.Mvvm | 必选 | Observable、Command、Validation、Messenger |
| 应用宿主 | Microsoft.Extensions.Hosting | 默认 | DI、配置、日志、后台服务和生命周期 |
| 配置 | Microsoft.Extensions.Configuration + Options | 默认 | appsettings.json、环境覆盖和强类型配置 |
| 序列化 | System.Text.Json | 默认 | JSON 序列化;避免无理由引入第二套 JSON 框架 |
| HTTP | IHttpClientFactory / Microsoft.Extensions.Http | 按联网需求 | 管理 HttpClient 生命周期和命名/类型化客户端 |
| 网络韧性 | Microsoft.Extensions.Http.Resilience | 按联网需求 | 超时、重试、熔断和限流;不要手写无限重试 |
| 单机数据库 | EF Core 10 + SQLite | 二选一 | 本地数据、迁移和查询 |
| 企业后端 | ASP.NET Core 10 API + EF Core 10 + SQL Server/Azure SQL | 二选一 | 多用户、权限、审计和中心数据 |
| 身份认证 | MSAL.NET / Microsoft.Identity.Client + Entra ID | 按身份需求 | 标准登录、令牌缓存和调用受保护 API |
| Windows 新能力 | Microsoft.WindowsAppSDK Stable | 按需 | 生命周期、窗口、资源、通知等 Windows 能力 |
| 原生 API | Microsoft.Windows.CsWin32 | 按需 | 类型安全、源生成的 Win32 P/Invoke |
| Web 混合内容 | Microsoft.Web.WebView2 | 按需 | 嵌入 Web 页面、编辑器、报表或可复用 Web 模块 |
| 日志抽象 | Microsoft.Extensions.Logging | 默认 | 业务代码只依赖统一日志接口 |
| 本地结构化日志 | Serilog + File/Async Sink | 默认推荐 | 轮转文件、诊断包和结构化字段;属于第三方依赖 |
| 遥测 | OpenTelemetry + Azure Monitor Exporter | 按产品/隐私需求 | Trace、Metric、Exception 和版本健康度 |
| 测试 | MSTest + Microsoft.Testing.Platform | 必选 | 单元、集成和测试运行平台 |
| UI 自动化 | FlaUI 或企业现有 UIA 工具 | 按风险 | Windows UI Automation;属于第三方方案 |
| 可访问性 | Accessibility Insights、Narrator、AutomationProperties | 必选质量门禁 | 键盘、读屏、高对比度和 UIA 检查 |
| 源码管理 | Git + GitHub 或 Azure Repos | 必选 | 分支、评审、审计和版本历史 |
| 包管理 | NuGet + Directory.Packages.props + lock file | 默认 | 统一依赖版本和可重复还原 |
| 静态质量 | SDK Analyzers + .editorconfig + dotnet format |
必选 | 风格、潜在缺陷和 CI 一致性 |
| CI/CD | GitHub Actions 或 Azure Pipelines Windows Agent | 必选 | 构建、测试、签名、打包和发布 |
| 包格式 | MSIX | 默认 | 安装、卸载、包标识和更新 |
| 内网替代 | ClickOnce | 按场景 | 已知用户群、简单内网更新 |
| 复杂安装替代 | WiX/MSI/EXE | 按场景 | 驱动、服务、复杂注册与传统企业要求 |
| 代码签名 | Store 自动签名;非 Store 使用 Azure Artifact Signing 或受信 OV 证书 | 发布必选 | 避免强 SmartScreen 阻断和保证来源完整性 |
| 更新 | Store、.appinstaller、Intune/ConfigMgr 或 ClickOnce |
发布必选 | 自动更新、分环、回滚与升级监控 |
| 文档 | README、ADR、部署 Runbook、隐私与遥测说明、Changelog | 必选 | 降低维护和交接风险 |
“必选”表示进入正式开发或发布前必须具备;“默认”表示多数中型项目推荐;“按需”表示需求出现并完成原型验证后才引入。
二、推荐解决方案结构¶
小到中型项目¶
Product/
├─ global.json
├─ Directory.Build.props
├─ Directory.Packages.props
├─ NuGet.config
├─ Product.sln
├─ src/
│ ├─ Product.App/ # WPF、View、ViewModel、App 启动与组合根
│ ├─ Product.Core/ # 领域、用例、接口,不依赖 WPF
│ └─ Product.Infrastructure/ # 数据库、HTTP、文件系统和平台实现
├─ tests/
│ ├─ Product.Core.Tests/
│ ├─ Product.Infrastructure.Tests/
│ └─ Product.UiTests/ # 确有价值时添加
├─ build/ # 打包、签名和 CI 脚本
└─ docs/ # ADR、运行手册和归档
大型或多产品项目¶
src/
├─ Product.App # WPF 入口和 Composition Root
├─ Product.Presentation # ViewModel、导航、对话框和 UI 状态
├─ Product.Domain # 领域模型和纯业务规则
├─ Product.Application # 用例、端口、DTO 和事务边界
├─ Product.Infrastructure # EF Core、HTTP、文件和外部系统
├─ Product.Platform.Windows # Windows App SDK、CsWin32、托盘、通知
└─ Product.Themes # 多应用共享主题时才独立
不要为了“架构看起来完整”创建大量空项目。小项目先使用三项目结构,只有依赖边界、多人协作或复用需求出现时再拆分。
依赖方向:
App / Presentation → Application → Domain
Infrastructure ─────→ Application / Domain
Platform.Windows ───→ Application abstractions
Domain 和 Application 不引用 WPF、EF Core、Windows App SDK 或具体日志实现。
三、UI 与设计系统闭环¶
1. UI 基线¶
- WPF 内置 Fluent Theme,默认跟随系统 Light/Dark。
- WPF Gallery 作为控件和视觉参考。
- Segoe UI Variable 作为主要字体。
- Segoe Fluent Icons 或统一矢量图标集。
- 页面使用 Grid、Auto、
*、Min/MaxWidth,避免固定像素布局。 - 主题切换资源使用
DynamicResource,不变的尺寸和结构使用StaticResource。
2. 设计令牌¶
Themes/
├─ Tokens.Colors.xaml
├─ Tokens.Typography.xaml
├─ Tokens.Spacing.xaml
├─ Theme.Light.xaml
├─ Theme.Dark.xaml
├─ Controls.Button.xaml
├─ Controls.Input.xaml
├─ Controls.DataGrid.xaml
└─ Components.xaml
设计令牌必须按语义命名,例如 AppSurfaceBrush、TextPrimaryBrush、AccentBrush、DangerBrush,不要在页面中重复写十六进制颜色。
3. 组件层级¶
同一业务组合重复三次以上再提取组件。只改属性时用 Style;改变视觉树时才写 ControlTemplate。重写模板必须覆盖 Normal、Hover、Pressed、Disabled、Focus、Validation 和 High Contrast。
4. MVVM 页面状态¶
使用:
ObservableObject/[ObservableProperty]。[RelayCommand]/[RelayCommand(CanExecute=...)]。AsyncRelayCommand和 CancellationToken。ObservableValidator+ DataAnnotations 处理常规输入验证。WeakReferenceMessenger只用于真正跨组件且不适合显式依赖的消息,不作为默认通信总线。
每个数据页面明确建模:
这些状态由 ViewModel 表达,View 通过绑定显示,避免在 code-behind 中堆业务状态机。
5. 导航和对话框¶
- 单窗口少页面:ContentControl + DataTemplate 映射 ViewModel。
- 多模块:定义小型
INavigationService、IDialogService接口。 - 不要仅为导航引入庞大全功能框架。
- 对话框返回强类型结果并支持取消,不通过全局静态 MessageBox 传播业务决策。
6. UI 质量门禁¶
每个核心页面验证:
Light / Dark / High Contrast
100% / 125% / 150% / 200% DPI
最小窗口 / 最大化 / 多显示器
中文 / 英文 / 长文本
鼠标 / 键盘 / Tab 顺序 / Narrator
Loading / Empty / Error / Validation / Offline
使用 Accessibility Insights 的 FastPass、Live Inspect 和 Narrator;可访问性是 PR/发布门禁,不是上线前一次性检查。
四、宿主、配置与生命周期¶
使用 Microsoft.Extensions.Hosting:
- DI:构造函数注入 ViewModel、窗口、用例和服务。
- Configuration:
appsettings.json、环境变量和受控的用户配置。 - Options:配置绑定为带验证的强类型对象。
- Logging:业务代码只依赖
ILogger<T>。 - HostedService:确有后台同步、设备监听或队列消费时使用。
App.xaml 删除 StartupUri,在 App.xaml.cs 创建 Host、注册服务、启动 Host、从 DI 获取 MainWindow,并在退出时停止/释放 Host。
推荐生命周期:
启动失败应显示可操作的错误信息和诊断文件位置,而不是无界面退出。
五、配置和本地文件¶
推荐:
- 可提交默认值:
appsettings.json。 - 用户设置:
%LocalAppData%\Company\Product\settings.json。 - 日志:
%LocalAppData%\Company\Product\Logs。 - 缓存:
%LocalAppData%\Company\Product\Cache。 - 需要漫游且不敏感的少量偏好才放
%AppData%。 - 每份设置包含 schema/version,升级时执行迁移。
- 写文件采用临时文件 + 原子替换,避免异常退出破坏配置。
不要在客户端配置中保存数据库管理员密码、API client secret、云密钥或可代表整个系统的服务端秘密。
六、数据架构的两条默认路线¶
路线 A:单机、本地优先¶
推荐包:
实践:
- 使用
IDbContextFactory<TContext>,每个工作单元创建短生命周期 DbContext。 - 数据操作使用异步 API,不阻塞 UI 线程。
- Migration 随版本管理;发布前测试升级路径。
- 破坏性迁移前自动备份本地数据库。
- 首次启动和升级失败提供恢复/导出路径。
- 不在 UI 直接操作 DbContext,Repository 也只在确实形成领域边界时添加。
路线 B:多用户、企业中心数据¶
WPF Public Client
→ HTTPS / MSAL access token
→ ASP.NET Core 10 Web API
→ Application/Domain
→ EF Core 10
→ SQL Server / Azure SQL
桌面客户端不应直接携带高权限 SQL Server 连接字符串。多用户系统通过后端统一执行:
- 身份验证与授权。
- 数据校验和业务规则。
- 审计、并发和事务。
- 密钥管理和限流。
- 数据库迁移和备份。
EF Core 10 与 .NET 10 对齐,并属于 LTS。数据库 provider 的主版本与 EF Core 保持一致,使用最新稳定补丁。
离线同步(按需)¶
只有明确需要离线时才增加:
- 本地 SQLite 缓存。
- Outbox/待同步队列。
- 幂等请求 ID。
- 冲突检测和产品定义的合并策略。
- 同步状态、失败重试和用户可见诊断。
不能只增加“失败后重试”,而不定义重复提交和冲突行为。
七、HTTP 与服务通信¶
默认使用:
为每个后端定义 typed client:
韧性策略:
- 每个请求有总超时。
- 只对明确的瞬时故障重试。
- 非幂等写请求不能盲目自动重试。
- 使用指数退避和 jitter。
- 连续失败启用 circuit breaker。
- 用户取消必须贯穿 CancellationToken。
- 日志记录 correlation ID、耗时和状态码,但不记录 token 和敏感正文。
Microsoft.Extensions.Http.Polly 已被弃用,新项目使用 Microsoft.Extensions.Http.Resilience。
八、身份、安全与隐私¶
身份¶
使用 Entra ID 时采用:
WPF 桌面应用属于 OAuth Public Client,不能安全保存 client secret。使用 Authorization Code + PKCE、系统浏览器或 WAM;令牌交给 MSAL cache 管理,不自己保存明文 refresh token。
本地敏感数据¶
- 用户凭据优先 Windows Credential Manager、WAM 或系统认证能力。
- 必须本地加密的小数据可用 Windows DPAPI,并定义换机/重装后的行为。
- 日志和遥测做字段白名单、脱敏和大小限制。
- 数据导出与诊断包必须明确提示包含的信息。
供应链¶
global.json固定稳定 SDK,allowPrerelease: false。Directory.Packages.props集中包版本。- 使用 lock file 和 CI
--locked-mode。 dotnet package list --vulnerable --include-transitive。- GitHub Dependabot、Renovate 或 Azure DevOps 等效工具自动提出依赖更新 PR。
- Preview/Experimental 包不得进入正式发布,除非有明确 ADR 和退出计划。
九、Windows 平台集成¶
选择顺序:
Windows App SDK¶
只为明确能力引入 Microsoft.WindowsAppSDK。非打包 WPF 项目通常配置:
同时明确 Runtime 是 framework-dependent 还是 self-contained,并在无开发环境的干净电脑验证。采用 MSIX 时不要机械套用 unpackaged 配置。
CsWin32¶
调用 User32、Shell32、Kernel32 等 Win32 API 时,使用 Microsoft.Windows.CsWin32 和 NativeMethods.txt 生成类型安全 P/Invoke,避免手写容易出错的 DllImport 签名。
WebView2¶
适合:
- 已存在且需要复用的 Web 功能。
- HTML 富文本/报表/在线帮助。
- 复杂 Web 编辑器或身份页面。
不适合把普通 WPF 表单全部改造成 Web。采用 Evergreen Runtime,并定义离线、版本、缓存、消息边界和安全策略。
十、日志、崩溃与可观测性¶
本地日志¶
业务代码使用 ILogger<T>;推荐以 Serilog 作为 provider:
日志要求:
- 结构化字段而非字符串拼接。
- 每日/大小轮转、保留天数和总容量上限。
- 包含 AppVersion、OS、Architecture、SessionId、CorrelationId。
- 不记录密码、token、完整个人信息或敏感业务正文。
- 提供“导出诊断包”,让用户主动提交选定日志。
捕获并记录:
Application.DispatcherUnhandledException。AppDomain.CurrentDomain.UnhandledException。TaskScheduler.UnobservedTaskException。
捕获不代表可以无条件继续运行。状态可能损坏的异常应记录、提示保存/恢复路径并安全退出。
远程遥测¶
需要远程监控时使用:
OpenTelemetry.Extensions.Hosting
Azure.Monitor.OpenTelemetry.Exporter
Application Insights / Azure Monitor
核心指标:
- 启动成功率和启动耗时。
- Crash-free session / version。
- API 成功率、延迟和超时。
- 数据库迁移成功率。
- 安装与更新成功率。
- 关键用户流程完成率。
启用遥测前定义用户告知、同意、地域、保留期限、采样、脱敏和关闭方式。桌面程序不会自动捕获所有 WPF 异常,需要在异常入口显式记录 OpenTelemetry Exception/Event。
十一、测试栈¶
单元与集成测试¶
默认:
新项目统一使用 MTP,不在同一解决方案测试配置中混用 MTP 和 VSTest。
测试分层:
- Domain/Application:纯单元测试,数量最多。
- ViewModel:状态、命令、验证、取消和错误分支。
- Infrastructure:真实 SQLite 临时库、HTTP fake server、文件系统边界。
- Contract:客户端 DTO 与 API OpenAPI/契约一致性。
- UI:少量高价值核心流程。
优先使用手写 Fake 测试业务边界,不要为每个类创建 Mock。只有验证复杂交互时才引入 Mock 框架。
UI 自动化¶
WPF UI 自动化可评估 FlaUI 或企业现有 UIA 框架。UI 测试需要交互式 Windows 桌面,普通云端 Hosted Runner 服务会话不一定能可靠运行,应使用专用 Windows 测试代理或虚拟机。
UI 测试只覆盖:
- 启动、登录和主导航。
- 核心业务 happy path。
- 权限/错误关键路径。
- 安装升级后的冒烟检查。
不要把所有业务逻辑都通过脆弱的 UI 自动化验证。
十二、代码质量与依赖管理¶
Directory.Build.props 推荐基线:
<Project>
<PropertyGroup>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<Deterministic>true</Deterministic>
</PropertyGroup>
</Project>
CI 中增加:
dotnet restore --locked-mode
dotnet format Product.sln --verify-no-changes --no-restore
dotnet build Product.sln -c Release --no-restore
dotnet test Product.sln -c Release --no-build
dotnet package list --vulnerable --include-transitive
推荐规则:
- CI 对新警告使用 warnings-as-errors;遗留项目分阶段收紧。
- 禁止无主人的 Analyzer suppression。
- 一个 UI PR 同时提交 Light/Dark 和关键状态截图。
- 架构决策写 ADR,包括框架、数据库、认证、打包和遥测选择。
- NuGet 主版本升级单独 PR,运行完整回归。
十三、CI/CD 闭环¶
流水线:
Checkout
→ 安装 global.json 指定的稳定 SDK
→ Restore locked
→ Format/Analyzer
→ Build Release
→ Unit/Integration tests + Coverage
→ Dependency vulnerability audit
→ Publish win-x64 / win-arm64(按目标)
→ 生成 SBOM/构件清单(组织需要时)
→ 签名
→ 打包 MSIX/MSI
→ 安装与启动冒烟测试
→ 上传不可变 Artifact
→ 发布到试点环
建议分离:
- PR pipeline:快速构建、单元测试、静态检查。
- Main pipeline:完整集成测试和候选构件。
- Release pipeline:审批、签名、打包、分发和回滚。
签名凭据必须保存在 CI secret store、HSM 或 Azure Artifact Signing 中,不放仓库、不放开发机共享文件夹。
十四、打包、签名、更新¶
默认:MSIX¶
适合新的商业和企业应用:
- Microsoft Store:Store 重签 MSIX,自动更新和差分下载。
- 企业:MSIX + Intune/Configuration Manager。
- 自有网站:MSIX +
.appinstaller,使用受信签名。
替代路线¶
- ClickOnce:WPF 内网、已知用户群、简单自动更新。
- WiX/MSI/EXE:需要驱动、Windows Service、复杂注册和自定义安装事务。
- Unpackaged/self-contained:简单工具;更新、签名和包标识自行负责。
签名¶
- Store MSIX:Store 免费重签。
- 非 Store:Azure Artifact Signing(地区满足时)或受信 OV 证书。
- 自签名:只用于开发测试,或企业 IT 已通过 Intune/Group Policy 下发信任。
更新闭环¶
每次发布保留:
- 上一个可回退安装包。
- 数据/设置迁移的向前兼容策略。
- Release Notes 和已知问题。
- 包哈希、签名信息和构建来源。
十五、监控与用户反馈闭环¶
发布后仪表盘按版本查看:
应用内提供:
- “关于”页面:版本、渠道、运行时和更新状态。
- “导出诊断信息”:用户确认后打包脱敏日志和配置摘要。
- “检查更新”。
- 反馈/支持入口,自动附带版本但不附带敏感数据。
每周或每个迭代执行:
没有日志、版本和更新结果的自动收集,就不能算完成交付闭环。
十六、推荐 NuGet 包集合¶
不要一次性全部安装。根据所在层和需求选择,版本在 Directory.Packages.props 中集中管理;Microsoft.Extensions 与 EF Core 使用与 .NET 10 对齐的最新稳定 10.0.x 补丁。
基础必选/默认¶
本地数据¶
HTTP¶
身份¶
Windows 能力¶
Microsoft.WindowsAppSDK # 明确需要时
Microsoft.Windows.CsWin32 # 调用 Win32 时
Microsoft.Web.WebView2 # 嵌入 Web 内容时
本地日志与遥测¶
Serilog.Extensions.Hosting
Serilog.Sinks.File
Serilog.Sinks.Async
OpenTelemetry.Extensions.Hosting # 远程遥测时
Azure.Monitor.OpenTelemetry.Exporter # Azure Monitor 时
测试¶
第三方包如 Serilog、FlaUI、WPF UI 或商业控件库必须经过许可证、维护活跃度、安全和升级兼容性评估。
十七、分阶段落地,避免过度设计¶
阶段 1:可运行基线¶
.NET 10 + WPF + Fluent Theme
CommunityToolkit.Mvvm
Generic Host + DI/Config/Logging
Core + App + Tests
Git + CI build/test
阶段 2:第一条纵向业务功能¶
阶段 3:可交付¶
阶段 4:可运营¶
阶段 5:按需扩展¶
最终推荐组合¶
对于典型联网企业桌面应用:
Client
├─ .NET 10 LTS / C# 14 / WPF
├─ WPF Fluent Theme + Design Tokens
├─ CommunityToolkit.Mvvm
├─ Microsoft.Extensions.Hosting
├─ HttpClientFactory + Http.Resilience
├─ MSAL.NET / Entra ID
├─ Windows App SDK / CsWin32(按需)
├─ Serilog 本地日志
└─ OpenTelemetry → Azure Monitor
Server
├─ ASP.NET Core 10 Web API
├─ Entra ID / Authorization Policies
├─ EF Core 10
├─ SQL Server / Azure SQL
└─ OpenTelemetry → Azure Monitor
Engineering
├─ GitHub/Azure Repos + PR
├─ MSTest + MTP
├─ Central Package Management + NuGet Audit
├─ GitHub Actions/Azure Pipelines
├─ Signed MSIX
├─ Store/AppInstaller/Intune 分环更新
└─ 监控 + 用户反馈 → Backlog
对于完全单机应用,将 Server 替换为 EF Core 10 + SQLite,其余开发、测试、签名、更新和监控闭环不变。
官方和项目资料¶
- Microsoft:.NET 10 概述
- Microsoft:WPF 使用 Generic Host
- Microsoft:CommunityToolkit.Mvvm
- Microsoft:WPF Fluent Theme 与样式模板
- Microsoft:EF Core 10
- Microsoft:HTTP Resilience
- Microsoft:MSAL.NET
- Microsoft:WPF 使用 Entra ID 登录
- Microsoft:在 WPF 中使用 Windows App SDK
- Microsoft:CsWin32
- Microsoft:WebView2
- Microsoft:MSTest 与 Microsoft.Testing.Platform
- Microsoft:Accessibility Insights 与可访问性测试
- Microsoft:Windows 打包与 MSIX
- Microsoft:代码签名选择
- Microsoft:Azure Monitor OpenTelemetry
- Serilog 官方项目