以下是对RegisterTypes方法的详细、系统性讲解,结合代码进行说明。
一、PrismRegisterTypes(IContainerRegistry containerRegistry)方法详解
RegisterTypes是 Prism 启动时最核心的依赖注册方法,用于告诉容器(Unity):
- 哪些接口对应哪些实现类
- 生命周期(单例 / 瞬时)
- 如何创建 View / ViewModel / Dialog
1. 你代码中用到的注册方法
protectedoverridevoidRegisterTypes(IContainerRegistrycontainerRegistry){// 1. 单例注册containerRegistry.RegisterSingleton<IAlarmQueue,AlarmQueue>();containerRegistry.RegisterSingleton<StationManager>();// 2. 具名注册(关键!解决你的错误)containerRegistry.Register<IHardwareDriver,MainBoardDriver>("MainBoard");containerRegistry.Register<IHardwareDriver,AuxPLCDriver>("AuxPLC");// 3. 普通接口到实现类的注册containerRegistry.Register<IMainBoardService,MainBoardService>();// 4. 视图导航注册containerRegistry.RegisterForNavigation<MainWindow,MainViewModel>();// 5. 对话框注册(可选)// containerRegistry.RegisterDialog<StatusDisplayView, StatusDisplayViewModel>("StatusDialog");}二、各注册方法的区别与用途
| 方法 | 含义 | 生命周期 | 使用场景 | 是否需要名称(Name) |
|---|---|---|---|---|
Register< TInterface, TImpl >() | 接口 → 实现类 | 瞬时(每次 Resolve 都 new 一个) | 普通 Service、Repository | 可选 |
RegisterSingleton< TInterface, TImpl >() | 接口 → 实现类 | 单例(全局只有一个实例) | 配置管理器、AlarmQueue、StationManager | 可选 |
Register< TInterface, TImpl >(string name) | 具名注册 | 瞬时 | 同一接口有多个实现(如 IHardwareDriver 有多个 Driver) | 必须 |
RegisterForNavigation<View, ViewModel>() | 视图导航注册 | 瞬时 | Prism Region 导航 | View 的名称 |
RegisterDialog<View, ViewModel>(string key) | 对话框注册 | 瞬时 | ShowDialog() 使用 | 对话框唯一标识 |
三、常用注册方法详解
1.RegisterSingleton<TInterface, TImpl>()
- 作用:全局只创建一个实例,之后所有
Resolve都返回同一个对象。 - 适用:配置管理器、日志、报警队列、数据库上下文等全局共享的对象。
- 示例:
containerRegistry.RegisterSingleton<IAlarmQueue,AlarmQueue>();containerRegistry.RegisterSingleton<StationManager>();
2.Register<TInterface, TImpl>()
- 作用:每次请求都创建一个新实例。
- 适用:大部分 Service、Repository。
- 示例:
containerRegistry.Register<IMainBoardService,MainBoardService>();
3.Register<TInterface, TImpl>(string name)——解决你当前错误的关键
- 作用:同一接口有多个不同实现时,必须使用具名注册。
- 你的场景:
IHardwareDriver有MainBoardDriver、AuxPLCDriver等多个实现,必须具名。 - 正确写法(已在你代码中):
containerRegistry.Register<IHardwareDriver,MainBoardDriver>("MainBoard");containerRegistry.Register<IHardwareDriver,AuxPLCDriver>("AuxPLC");
4.RegisterForNavigation<View, ViewModel>()
- 作用:注册页面导航。
- 使用:
regionManager.RequestNavigate("ContentRegion", "MainWindow"); - 示例:
containerRegistry.RegisterForNavigation<MainWindow,MainViewModel>();
5.RegisterDialog<View, ViewModel>(string dialogKey)
- 作用:注册弹窗。
- 使用:
dialogService.ShowDialog("StatusDialog", parameters, callback); - 示例:
containerRegistry.RegisterDialog<StatusDisplayView,StatusDisplayViewModel>("StatusDialog");
四、注入方式 vs 反射(Activator.CreateInstance)的区别
| 维度 | 依赖注入 (DI) | 反射 (Activator.CreateInstance) |
|---|---|---|
| 原理 | 容器统一管理依赖关系 | 运行时动态创建对象 |
| 解耦性 | 优秀(接口编程) | 较差(需知道具体类型) |
| 可测试性 | 优秀(容易 Mock) | 差 |
| 生命周期管理 | 优秀(Singleton、Scoped、Transient) | 几乎无 |
| 性能 | 稍有损耗(首次) | 较快 |
| 维护性 | 高 | 低(硬编码类型名) |
| 错误发现时机 | 启动时(RegisterTypes) | 运行时 |
| 适用场景 | 大型项目、工业级软件 | 简单工具、插件系统 |
结论:强烈推荐使用依赖注入,尤其在 WPF + Prism 项目中。
五、最终推荐的RegisterTypes写法(完整版)
protectedoverridevoidRegisterTypes(IContainerRegistrycontainerRegistry){// 1. 公共单例containerRegistry.RegisterSingleton<StationManager>();containerRegistry.RegisterSingleton<IAlarmQueue,AlarmQueue>();containerRegistry.RegisterSingleton<RepositoryFactory>();// 2. 驱动 - 具名注册(关键!)containerRegistry.Register<IHardwareDriver,MainBoardDriver>("MainBoard");containerRegistry.Register<IHardwareDriver,AuxPLCDriver>("AuxPLC");containerRegistry.Register<IHardwareDriver,LoadMonitorDriver>("LoadMonitor");containerRegistry.Register<IHardwareDriver,RFIDDriver>("RFID");containerRegistry.Register<IHardwareDriver,ScannerDriver>("Scanner");// 3. Service 注册containerRegistry.Register<IMainBoardService,MainBoardService>();containerRegistry.Register<IAuxCtrlService,AuxCtrlBoardService>();containerRegistry.Register<ILoadMonitorService,LoadMonitorService>();containerRegistry.Register<IRFIDService,RFIDService>();containerRegistry.Register<IScannerService,ScannerService>();// 4. 视图导航containerRegistry.RegisterForNavigation<MainWindow,MainViewModel>();}请确认:
- 所有 Service 的构造函数第一个参数必须是
IHardwareDriver driver RegisterTypes中必须有上面的具名驱动注册- 清理解决方案 → 重新生成