深入 optimizerDuck 的 DI 容器:单例注册与页面自动装配完全指南
深入 optimizerDuck 的 DI 容器单例注册与页面自动装配完全指南【免费下载链接】optimizerDuckFree, open-source Windows optimization tool for performance, privacy, and simplicity.项目地址: https://gitcode.com/GitHub_Trending/op/optimizerDuck optimizerDuck 是一款免费的开源 Windows 优化工具主打性能调优、隐私保护与系统简化。对开发者来说它最值得学习的是那套干净利落的DI 容器设计基于Microsoft.Extensions.DependencyInjection的单例注册策略加上反射扫描 自定义特性实现的页面自动装配让新增一个功能页面几乎零胶水代码。一、DI 容器搭建一行 Host 构建器搞定全家桶optimizerDuck 的依赖注入容器在 App.xaml.cs 中完成搭建使用的是 .NET 官方的通用主机_host Host.CreateDefaultBuilder() .UseSerilog() .ConfigureServices((context, services) { /* 全部服务注册 */ }) .Build();在 optimizerDuck.csproj 中可以看到它依赖的两个核心包Microsoft.Extensions.DependencyInjection和Microsoft.Extensions.Hosting均为 10.x 版本目标框架net10.0-windows。这意味着容器天生自带配置绑定IOptionsMonitorAppSettings、日志ILoggerT等基础设施开发者不需要自己写任何工厂代码。二、单例注册为什么几乎全部是 AddSingleton打开注册清单App.xaml.cs你会发现一个鲜明的特征——几乎没有 AddTransient全部是 AddSingleton类别注册内容位置️ 窗口层MainWindow、MainWindowViewModelApp.xaml.cs#L325-L326 页面层DashboardPage、OptimizePage、SettingsPage等 7 组 Page ViewModelApp.xaml.cs#L329-L352⚙️ 服务层OptimizationRegistry、OptimizationService、RevertManager、SystemInfoService等App.xaml.cs#L359-L373这种全单例策略背后有明确的工程理由WPF 页面是长生命周期对象。页面被导航栏持有反复创建只会浪费内存并丢失 UI 状态单例天然匹配。服务持有状态。OptimizationRegistry要预加载全部优化项、RevertManager要维护回滚记录这些状态必须唯一共享。服务之间互相引用。全单例避免了瞬态服务持有单例导致的 captive dependency被捕获依赖陷阱。一个细节值得关注WPF-UI 的 UI 服务按接口注册如services.AddSingletonISnackbarService, SnackbarService()App.xaml.cs#L320-L322而业务服务按具体类注册。接口抽象只留在需要替换或隔离的边界对话框、导航、Toast内部服务直接引用具体类更简单直接。三、页面自动装配反射扫描 特性绑定真正体现设计功力的是 optimizerDuck 如何注册那些优化分类页。项目里有 7 大优化分类性能、GPU、电源管理、AI……和 4 个定制分类如果手写注册App.xaml.cs会再膨胀一倍。作者用两个扩展方法解决了它。3.1 特性声明把分类和页面绑在一起每个优化分类类上都挂着一个自定义特性例如 Performance.cs[OptimizationCategory(typeof(PerformanceOptimizerPage))] public class Performance : IOptimizationCategory { ... }OptimizationCategoryAttribute 只有一个属性PageType用于声明这个分类对应哪个 XAML 页面。定制分类同理使用 CustomizeCategoryAttribute 携带可选的PageType。3.2 反射扫描自动发现所有分类两个入口方法在App.xaml.cs中被调用services.AddAllCustomizeCategoryPages()和services.AddAllOptimizationPages()。以 OptimizationPageRegistryExtensions.cs 为例逻辑只有三步调用 ReflectionHelper.FindImplementationsInLoadedAssemblies 扫描所有已加载程序集找出实现了IOptimizationCategory的类读取每个类上的OptimizationCategoryAttribute拿到PageType把页面类型注册为单例工厂方法稍后解析依赖并创建 ViewModel。反射扫描本身也做了工程化保护ReflectionHelper.cs只扫程序集名以optimizerDuck开头的程序集避免遍历系统程序集结果带锁缓存_implementationCache扫描只发生一次SafeGetTypes捕获ReflectionTypeLoadException部分类型加载失败时降级返回可用类型不会让启动流程崩掉。3.3 工厂方法延迟解析组装页面注册时并不立即创建页面而是交给一个工厂 lambdaOptimizationPageRegistryExtensions.cs#L29-L32。当导航栏第一次请求该页面时工厂才从容器取出 8 个依赖——OptimizationRegistry、OptimizationService、RevertManager、ISnackbarService、IContentDialogService、SystemInfoService、ILoggerT、IOptionsMonitorAppSettings——组装出OptimizationCategoryViewModel再调用Activator.CreateInstance(pageType, viewModel)生成页面实例OptimizationPageRegistryExtensions.cs#L36-L65。定制分类页的装配逻辑几乎对称见 CustomizePageRegistryExtensions.cs区别只是依赖的是CustomizeRegistry并额外注入IRegistryWatcher用于监听注册表变化实时刷新状态。页面本身非常薄如 OptimizationPages.cs 中的PerformanceOptimizerPage构造函数只接收 ViewModel 并初始化 XAML。四、这套设计的收益新增页面只需两件事理解整个流程后你会发现扩展成本被压到了最低✅新增一个优化分类写一个IOptimizationCategory实现类打上[OptimizationCategory(typeof(XxxPage))]再写一个继承OptimizationPage的页面类——不需要改动App.xaml.cs一行代码。✅依赖集中可见每个页面的依赖清单都明明白白写在工厂方法里方便排查。✅状态安全全单例 WPF 长生命周期页面的特性完全匹配杜绝重复创建。⚠️代价反射扫描依赖程序集命名约定optimizerDuck*前缀若拆分子程序集需要注意命名另外单例泛滥会让单元测试更依赖桩项目的测试工程 optimizerDuck.Test 就为此提供了StubOptimization等测试替身。五、小结给 WPF 开发者的三个可复用套路Host 构建器起步Host.CreateDefaultBuilder()一次性获得 DI 配置 日志UseSerilog()无缝接入文件日志App.xaml.cs#L292-L301。单例为王接口留边界WPF 桌面应用默认AddSingleton仅在需要替换实现的地方引入接口。特性 反射做自动装配用[XxxCategory(PageType)]风格特性把数据模型与 UI 页面绑定配合带缓存、带容错的反射扫描实现写代码即注册。optimizerDuck 把 Windows 系统优化做成了开箱即点的体验而它的 DI 容器设计同样值得你直接搬回自己的 WPF 项目中。✨【免费下载链接】optimizerDuckFree, open-source Windows optimization tool for performance, privacy, and simplicity.项目地址: https://gitcode.com/GitHub_Trending/op/optimizerDuck创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →