当前位置: 首页 > news >正文

WPF-Control核心架构思想

WPF-Control 项目架构详解

一、核心架构思想

这个项目的架构可以用一句话概括:

控件负责显示,服务负责能力,模块负责组合,主题负责外观,ApplicationBase 负责生命周期,IOC 负责连接所有对象。

这是一种典型的分层模块化架构,各个组件职责清晰,松耦合,易于扩展和维护。


二、分层关系详解

2.1 分层架构图

┌─────────────────────────────────────────────────────────────┐ │ App / Tests │ ← 应用入口/测试层 ├─────────────────────────────────────────────────────────────┤ │ ApplicationBase │ ← 生命周期管理 ├─────────────────────────────────────────────────────────────┤ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ IOC │ │ Services │ │ Modules │ │ ← 核心服务层 │ └──────────┘ └──────────┘ └──────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ Themes / Styles / Controls / Presenters │ ← UI展示层 └─────────────────────────────────────────────────────────────┘

2.2 各层职责说明

层级职责典型文件/组件
App应用入口,继承ApplicationBaseApp.xaml.cs
ApplicationBase生命周期管理、异常处理、启动流程ApplicationBase.cs
IOC依赖注入容器,连接所有对象Ioc.cs,IocExtension.cs
Services提供各种业务能力(数据库、日志、消息等)ILogService,IMessageService
Modules功能模块组合,封装业务单元HomeBox,ProjectModule
Themes/Styles外观样式管理Generic.xaml,Share.xaml
Controls/PresentersUI控件和视图逻辑TagBox,HomeViewPresenter

三、运行流程剖析

3.1 完整启动流程

启动 App │ ├─→ 创建 ServiceCollection (DI容器构建) │ ├─→ ConfigureServices 注册模块和服务 │ ├─→ Ioc.Build 构建容器 │ ├─→ 加载多语言 (ILoadGlobalizationOptionsService) │ ├─→ Configure 应用配置 │ ├─→ 加载主题 (ILoadThemeOptionsService) │ ├─→ 显示启动页 (SplashScreen) │ ├─→ 执行登录 (ILoginViewPresenter) │ ├─→ 创建并显示主窗口 │ └─→ 用户操作控件 → Command / Presenter / Service 响应

3.2 核心流程代码解析

第一步:应用启动入口
publicpartialclassApp:ApplicationBase{protectedoverridevoidConfigureServices(IServiceCollectionservices){// 注册应用服务services.AddApplicationServices();// 注册项目服务services.AddProject<AIDIProjectService>(x=>x.UseOpenCurrentOnLoad=false);// 注册模块services.AddHome<ProjectThumbnialHomeViewPresenter>();// 注册标签服务services.AddTag<ProjectTagService>(x=>{x.Tags.Add(newTag(){Name="训练数据",Background=Brushes.Green});x.Tags.Add(newTag(){Name="测试数据",Background=Brushes.Gray});});// 注册数据库services.AddDbContextBySetting<AIDIDataContext>();services.AddSingleton<IStringRepository<fm_dd_image>,DbContextRepository<AIDIDataContext,fm_dd_image>>();}protectedoverrideWindowCreateMainWindow(StartupEventArgse){returnnewMainWindow();}}

关键要点

  • ConfigureServices方法用于注册所有服务和模块
  • 使用扩展方法链式调用,代码清晰优雅
  • 支持配置回调,可在注册时进行初始化配置
第二步:ApplicationBase 初始化
publicabstractpartialclassApplicationBase:Application{publicApplicationBase(){this.ShutdownMode=ShutdownMode.OnMainWindowClose;AppPaths.Register(this.CreateAppPathServce());this.InitExcetion();// 初始化异常处理this.InitServiceCollection();// 初始化服务容器}protectedvoidInitServiceCollection(){ServiceCollectionsc=newServiceCollection();this.ConfigureServices(sc);// 调用子类的配置Ioc.Build(sc);// 构建IOC容器// 在显示页面前加载多语言Ioc.GetService<ILoadGlobalizationOptionsService>(false)?.Load(outstringmessage);}}

关键要点

  • 构造函数执行顺序:异常处理 → 服务注册 → 多语言加载
  • Ioc.Build(sc)是核心,将所有服务注册到容器
第三步:OnStartup 启动流程
protectedoverridevoidOnStartup(StartupEventArgse){this.Configure();// 应用配置this.OnSingleton(e);// 单例检查base.OnStartup(e);Windowwindow=this.CreateMainWindow(e);// 主窗口加载完成后执行window.Loaded+=(s,e)=>{varloads=Ioc.GetAssignableFromServices<IMainWindowLoadedLoadable>().Distinct();foreach(variteminloads)item.Load(outstringmessage);};this.OnSplashScreen(e);// 显示启动页this.OnLogin();// 执行登录Ioc<IMainWindowSavableService>.Instance?.Load(window);this.MainWindow.Show();}

关键要点

  • 启动流程:配置 → 单例检查 → 启动页 → 登录 → 主窗口
  • 通过Ioc.GetAssignableFromServices<T>()实现批量服务调用

四、核心组件详解

4.1 IOC 容器

IOC(控制反转)是整个架构的核心连接器,负责管理所有对象的创建和依赖注入。

publicstaticclassIoc{privatestaticIServiceProvider_services=null;publicstaticIServiceProviderServices=>_services;publicstaticvoidBuild(IServiceCollectionserviceCollection){_services=serviceCollection.BuildServiceProvider();}publicstaticTGetService<T>(boolthrowIfNone=true){if(_services==null)returnthrowIfNone?thrownewArgumentNullException(...):default;returnGetService<T>(typeof(T),throwIfNone);}// 通过类型获取服务publicstaticTGetService<T>(Typetype,boolthrowIfNone=true){Tr=(T)_services.GetService(type);if(r==null&&throwIfNone)thrownewArgumentNullException(...);returnr;}// 获取所有实现了某个接口的服务publicstaticIEnumerable<T>GetAssignableFromServices<T>(Func<T,bool>predicate=null){foreach(ServiceDescriptoritemin_serviceCollection){if(typeof(T).IsAssignableFrom(item.ServiceType)){// 遍历所有符合条件的服务实例...}}}}

IOC 使用场景

场景代码示例
获取单例服务Ioc.GetService<ILogService>()
安全获取(不抛异常)Ioc.GetService<IMyService>(false)
获取多个服务Ioc.GetAssignableFromServices<ISplashLoadable>()
XAML 绑定<IocExtension Type="{x:Type local:MyService}" />

4.2 ApplicationBase 生命周期

ApplicationBase封装了 WPF 应用的完整生命周期:

构造函数 │ ├─→ InitExcetion() // 注册异常处理 │ ├─→ DispatcherUnhandledException │ ├─→ AppDomain.UnhandledException │ └─→ TaskScheduler.UnobservedTaskException │ └─→ InitServiceCollection() ├─→ 创建 ServiceCollection ├─→ ConfigureServices() └─→ Ioc.Build() OnStartup │ ├─→ Configure() // 应用配置 ├─→ OnSingleton() // 单例检查 ├─→ OnSplashScreen() // 启动页 ├─→ OnLogin() // 登录 └─→ Show MainWindow OnExit │ ├─→ 停止定时任务 ├─→ 记录退出日志 └─→ 保存操作记录

4.3 模块系统

模块是功能的封装单元,通过扩展方法注册:

publicstaticclassExtension{publicstaticIServiceCollectionAddHome<T>(thisIServiceCollectionservices,Action<IHomeOptions>setupAction=null)whereT:class,IHomeViewPresenter{services.AddOptions();services.TryAdd(ServiceDescriptor.Singleton<IHomeViewPresenter,T>());if(setupAction!=null)services.Configure(newAction<HomeOptions>(setupAction));returnservices;}}

模块注册模式

  1. 定义接口(如IHomeViewPresenter
  2. 实现具体类(如ProjectThumbnialHomeViewPresenter
  3. 通过扩展方法注册到 IOC
  4. 在需要的地方通过接口获取实例

五、项目结构实践

5.1 推荐的项目目录结构

Source/ ├── App/ # 应用程序 │ └── H.App.AIDI/ # 具体应用 │ ├── App.xaml.cs # 入口 │ ├── MainWindow.xaml # 主窗口 │ └── ViewModel/ # 视图模型 ├── Base/ # 基础组件 │ ├── H.Attach/ # 附加属性 │ └── H.Mvvm/ # MVVM框架 ├── Controls/ # 自定义控件 │ ├── H.Controls.TagBox/ # 标签控件 │ └── H.Controls.Form/ # 表单控件 ├── Modules/ # 功能模块 │ └── H.Modules.Home/ # 首页模块 ├── Providers/ # 服务提供者 │ └── H.Iocable/ # IOC容器 ├── Services/ # 服务层 │ └── H.Services.Common/ # 公共服务 └── Styles/ # 样式主题 └── H.Style/ # 全局样式

5.2 创建新模块的步骤

假设我们要创建一个"设置"模块:

步骤1:定义接口

publicinterfaceISettingViewPresenter:IViewPresenter{voidShow();}

步骤2:实现 Presenter

publicclassSettingViewPresenter:ISettingViewPresenter{publicvoidShow(){// 显示设置窗口逻辑}}

步骤3:创建扩展方法

publicstaticclassSettingExtension{publicstaticIServiceCollectionAddSetting(thisIServiceCollectionservices){services.TryAddSingleton<ISettingViewPresenter,SettingViewPresenter>();returnservices;}}

步骤4:在 App 中注册

protectedoverridevoidConfigureServices(IServiceCollectionservices){services.AddSetting();}

步骤5:使用模块

Ioc.GetService<ISettingViewPresenter>().Show();

六、最佳实践总结

6.1 设计原则

  1. 单一职责:每个类只做一件事(控件只负责显示,服务只提供能力)
  2. 依赖倒置:依赖抽象而非具体实现
  3. 接口隔离:使用细粒度接口,避免胖接口
  4. 开闭原则:对扩展开放,对修改关闭

6.2 代码规范

// ✅ 推荐:依赖接口publicclassMyPresenter{privatereadonlyILogService_logService;publicMyPresenter(ILogServicelogService){_logService=logService;}}// ❌ 不推荐:依赖具体类publicclassMyPresenter{privatereadonlyLogService_logService=newLogService();}

6.3 服务注册规范

生命周期使用场景注册方式
Singleton全局共享服务(日志、配置)AddSingleton
Scoped每个请求/窗口独立AddScoped
Transient每次获取新实例AddTransient

七、总结

WPF-Control 的架构设计体现了以下核心价值:

  1. 高内聚低耦合:各层职责清晰,模块独立
  2. 可扩展性强:通过 IOC 和接口实现松耦合扩展
  3. 易于测试:依赖注入使单元测试更简单
  4. 统一生命周期:ApplicationBase 统一管理应用生命周期

通过理解这个架构模式,您可以:

  • 快速上手项目开发
  • 按照规范创建新模块
  • 高效定位和解决问题
  • 参与项目贡献

http://www.jsqmd.com/news/852485/

相关文章:

  • 极域电子教室破解指南:如何安全解除机房电脑限制的完整教程
  • 工业产线激光打标系统如何选型 | 罗色科技 Lugsicher
  • 从沙子到车辙(3.4):流水线——指令级并行的艺术
  • 餐饮供应链行业如何做线上推广获客?2026全网获客指南与服务商盘点 - 优质企业观察收录
  • 严格因果的零泄露白盒框架——从哈密顿能量守恒到希尔伯特相位流形的工业故障早期预警
  • 2026伊宁市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,5月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一休修缮
  • 矩阵运营的技术底座:为什么“一体化系统“正在取代“工具拼装“
  • Unity事件(Event)实战避坑:从金币系统到UI更新,我踩过的3个坑和解决方案
  • 告别Modelsim命令行!用Notepad++插件NppExec一键检查Verilog语法(附详细配置命令)
  • GRP (18-27) (human, porcine, canine) (Neuromedin C (porcine));GNHWAVGHLM-NH₂
  • 如何在5分钟内实现专业级直播背景替换:obs-backgroundremoval插件完全指南
  • Python 四大常用装饰器最全对比
  • 外贸模板建站服务商推荐,2026年高适配款出炉 - FaiscoJeff
  • docker启动线程创建异常 pthread_create EPERM | RuntimeError: can‘t start new thread
  • VSCode在Ubuntu/WSL2里保存文件总报permission denied?可能是这个虚拟化环境特有的坑
  • 2026仓库管理软件厂家优选指南:中小企业数字化仓储选型必看 - 深度智识库
  • Dify工作流引擎架构演进:从低代码到智能编排的技术深度解析
  • 浏览器端音乐文件解密技术深度解析:Unlock Music项目架构与实现原理
  • Perplexity习语查询功能实战指南:3步精准定位地道表达,告别中式英语(附12个高频误用对照表)
  • Windows上的B站原生客户端:如何告别浏览器卡顿,享受丝滑观看体验?
  • AnyKernel3终极指南:5分钟打造通用Android内核刷机包
  • 2026年5月最新美度官方售后网点权威数据验证报告(含迁址新开)实地考察多方对比 - 亨得利官方服务中心
  • 绝绝子!输入关键词,这几款AI论文工具直接生成结构完整的毕业论文
  • GRO淘金优化算法实战:5个工程优化问题调参与性能对比
  • 2026年宁夏注塑机销售公司版图:区域服务商全链路服务分析报告出炉! - 深度智识库
  • 2026东莞户外蚊虫防控全攻略:选型、避坑与实测推荐 - 品牌优选官
  • 别再让VmmemWSL吃光你的内存!手把手教你用.wslconfig给Docker on WSL2瘦身
  • Claude Code 扩展体系
  • DeepSeek R1模型API调用性能对比:v1.2 vs v2.1吞吐量提升47%,但90%开发者忽略了这个Header配置
  • Windows风扇控制终极指南:用FanControl打造静音高效的电脑散热系统