WPF MVVM实战系列教程(四、Prism中的依赖注入)

🧭 WPF MVVM入门系列教程


🍠 WPF MVVM进阶系列教程


⌨️ WPF MVVM实战系列教程


依赖注入

Prism 内置了对依赖注入的支持,默认使用UnityDryIoc作为 DI 容器。其核心思想是:

  • 将服务的创建和管理交给 DI 容器,而非手动new
  • 通过构造函数注入、属性注入等方式获取依赖
  • 支持服务的生命周期管理(Transient、Singleton、Scoped)

本系列教程以Unity作为DI容器进行演示(DryIoc除了配置和注入时有点小区别,使用方面无异) 

 

如何配置不同的DI容器

DryIoc

1、安装Prism.Wpf包和Prism.DryIoc包

image

 

2、修改App.xaml,将App类替换为Prism.DryIoc.PrismApplication类并移除StartupUri

1 <prism:PrismApplication x:Class="_12_Prism_Ioc.App"
2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4              xmlns:local="clr-namespace:_12_Prism_Ioc"
5              xmlns:prism="http://prismlibrary.com/">
6     <Application.Resources>
7          
8     </Application.Resources>
9 </prism:PrismApplication>

 

3、改造App类,使之继承自Prism.DryIoc.PrismApplication类

改造后的App类和前面介绍的Bootstrapper类结构一致

 

4、在RegisterTypes函数中注册类型到容器中

 

示例代码如下:

 1  public partial class App : PrismApplication
 2  {
 3      // 1. 配置主窗口(Prism 启动时加载)
 4      protected override Window CreateShell()
 5      {
 6          // DryIoc 会自动解析 MainWindow(依赖注入)
 7          return Container.Resolve<MainWindow>();
 8      }
 9 
10      // 2. 注册服务到 DryIoc 容器
11      protected override void RegisterTypes(IContainerRegistry containerRegistry)
12      {
13          // ========== 基础注册方式 ==========
14          // 单例注册(全局唯一)
15          containerRegistry.RegisterSingleton<IMessageService, MessageService>();
16 
17          // 瞬时注册(每次解析新建实例)
18          containerRegistry.Register<IDataService, DataService>();
19 
20          // 若需要使用 DryIoc 原生 API,可通过 Container 转换
21          var dryIocContainer = containerRegistry.GetContainer();
22 
23          //dryIocContainer是DryIoc原生容器对象,可以参考DryIoc文档了解详细使用
24          //https://github.com/dadhi/DryIoc
25 
26          // 注册视图(Prism 导航用)
27          containerRegistry.RegisterForNavigation<HomeView>();
28      }
29 
30      // 3. 可选:模块化配置(若使用模块)
31      protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
32      {
33          base.ConfigureModuleCatalog(moduleCatalog);
34          // 注册模块(示例)
35          // moduleCatalog.AddModule<MyModule>();
36      }
37  }

 

 

Unity

1、安装Prism.Wpf包和Prism.Unity包

 

2、创建Bootstrapper

 1   public class Bootstrapper : PrismBootstrapper
 2   {
 3       protected override DependencyObject CreateShell()
 4       {
 5           return Container.Resolve<MainWindow>();
 6       }
 7 
 8       protected override void RegisterTypes(IContainerRegistry containerRegistry)
 9       {
10           
11       }
12   }

 

3、移除App.xaml中的StartupUri

image

 

4、修改App类,重写Startup函数,启动Bootstrapper

 1  public partial class App : Application
 2  {
 3      protected override void OnStartup(StartupEventArgs e)
 4      {
 5          base.OnStartup(e);
 6 
 7          Bootstrapper bootstrapper = new Bootstrapper();
 8          bootstrapper.Run();
 9      }
10  }

 

Prism框架提供的服务

在前面介绍Bootstrapper的职责时,其中包含了一项自动初始化 Prism 的关键服务。

 

Prism框架为我们提供了以下服务

IRegionManager:管理视图区域(Region),实现视图的动态加载 / 切换;
IEventAggregator:实现模块间的无耦合通信;
IDialogService:统一管理对话框;
INavigationService:实现视图导航。

 

在Bootstrapper初始化时,框架会帮我们注入这些服务的实例到容器中。

后面我们在使用时,就可以直接从容器中去取。

这里暂时不做进一步演示,等介绍到对应的服务时,再进行演示。

 

如何注册自己的类型

首先我们创建服务接口/类

 1 // 服务接口
 2 public interface IMessageService
 3 {
 4     string GetMessage();
 5 }
 6 
 7 // 服务实现
 8 public class MessageService : IMessageService
 9 {
10     public string GetMessage()
11     {
12         return "Hello Prism DI!";
13     }
14 }

 

然后在RegisterTypes函数中进行注册

1  protected override void RegisterTypes(IContainerRegistry containerRegistry)
2  {
3      containerRegistry.Register<IMessageService, MessageService>();
4  }

 

Prism提供了三个注册类型的接口

Register:Transient,每次service请求都是获得不同的实例.

RegisterScoped:对于同一个请求返回同一个实例,不同的请求返回不同的实例.

RegisterSingleton:每次都是获得同一个实例, 单一实例模式.

 

此外,Prism还提供一种注册视图与 ViewModel(自动关联)的方式

这种方式在后面进行导航时会经常用到

1 protected override void RegisterTypes(IContainerRegistry containerRegistry)
2 {
3      containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
4 }

 

如何使用Unity的原生接口

通过下面的语句,就可以获取Unity原生容器对象

1 var unityContainer = containerProvider.GetContainer()

 Unity原生的注册方式会有点小区别,可以参考Unity的文档

1 unityContainer.RegisterType<IMessageService, MessageService>("Service1", new Unity.Lifetime.ContainerControlledLifetimeManager());

 

 

如何注册同一个接口的不同实现

我们可以通过给实例命名的方式实现

1  containerRegistry.Register<IMessageService, MessageService>("ServiceA");
2  containerRegistry.Register<IMessageService, MessageService>("ServiceB");

 

如何使用容器中注入的对象

 

posted @ 2026-01-20 14:12  zhaotianff  阅读(2)  评论(0)    收藏  举报