• Prism 实现依赖注入


    安装

    首先安装Prism.Unity包

    项目改造:

    修改App.xaml

    1. 屏蔽掉StartupUri="MainWindow.xaml"
    2. 添加 xmlns:prism="http://prismlibrary.com/"
    3. 修改Application标签为prism:PrismApplication,prism:PrismApplication也是继承自Application,她对Application进行了扩展
    1. <prism:PrismApplication x:Class="TestSpectrum.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:TestSpectrum"
    5. xmlns:prism="http://prismlibrary.com/"
    6. >
    7. <Application.Resources>
    8. Application.Resources>
    9. prism:PrismApplication>

    修改App.xaml.cs

    1.  继承 PrismApplication
    2.  重写以下方法

    注意这里我们可以直接通过Container.Resolve从容器中获取实例

    1. public partial class App : PrismApplication
    2. {
    3. protected override Window CreateShell()
    4. {
    5. // 通过容器创造主界面实例
    6. return Container.Resolve();
    7. }
    8. // 初始化Shell(主窗口)的时候执行这个方法
    9. protected override void InitializeShell(Window shell)
    10. {
    11. // 可以用于实现登录逻辑,以下是伪代码
    12. var loginWin = Container.Resolve();// 创建一个窗口对象
    13. if (loginWin == null || loginWin.ShowDialog() != true)// 以模态窗口的方式打开这个窗口对象
    14. {
    15. // 不需要App的属性ShutdownMode配合
    16. Application.Current.Shutdown();
    17. // 如果没有强行退出的话,打开主窗口
    18. }
    19. }
    20. ///
    21. /// 用于注册一些内容
    22. ///
    23. ///
    24. ///
    25. protected override void RegisterTypes(IContainerRegistry containerRegistry)
    26. {
    27. containerRegistry.RegisterSingleton(typeof(OmniDriver.NETWrapper));
    28. containerRegistry.RegisterSingleton();
    29. //Prism.Unity.UnityContainerExtension
    30. }
    31. }

    容器注册

    这里我们重点关注,RegisterTypes这个方法,它会在程序启动后被框架调用。

    传进来一个参数,containerRegistry,它的类型其实是UnityContainerExtension,这里用接口IContainerRegistry来接收这个变量。这里注意UnityContainerExtension实现了多个接口,其中就包含了包含了IContainerRegistry 和 IContainerProvider(后面会说到)。

    当 RegisterTypes别调用后,我们利用containerRegistry向容器注册内容,这些注册了的内容,就可以在其他地方实现自动注入了。

    IOC和工厂模式的思路是一样的,将需要new的地方(程序不稳定的地方)统一隔离在一个地方。IOC其实就是一个超级工厂。

    这里我们用RegisterSingleton进行注册。

    1. containerRegistry.RegisterSingleton(typeof(OmniDriver.NETWrapper));
    2. containerRegistry.RegisterSingleton();

    单独类注册

    第一句注册了单个类,那么我们可以利用特性[Unity.Dependency] 自动注入这个类的实例到其他的类。 

    接口和实现类的注册

    第二句注册了一个接口和对应的实现类,那么我们可以自动注入接口,程序运行起来后,容器会自动帮我们实例化这个类并赋值給该接口。

     注册的生命周期,Register和RegisterSingleton

    这里我们也可以用Register,区别在于实例的生命周期,RegisterSingleton表示注册的实例时单例模式,每次找容器取实例时,取到的是第一次的实例化的那一个,如果是Register注册的实例则下次找容器要的话得到是新的实例。

    之前,我们直接通过Container.Resolve();拿到的对象呢?它并没有注册?那再次拿的话会是同一个吗?我们做个实验。

     也就是说,没有注册时,Container.Resolve();每次拿到的时新的对象,

    但是如果我加上一句:containerRegistry.RegisterSingleton();

     再次运行:

     程序启动之后,我再想注册怎么办?

    目前我们只能通过RegisterTypes回调来注册,要想在其他地方注册,怎么办?关键是拿到对象,containerRegistry。

    我们可以先利用 Application.Current as App 得到当前的App对象,然后app对象里有个Container属性,这个和之前的containerRegistry其实就是一个对象(都是UnityContainerExtension的实例),不过它此时的类型是IContainerProvider,我们可以直接将其转换成IContainerRegistry,这样就可以调用注册方法了,如下:

    1. var a = System.Windows.Application.Current as App;
    2. var c = (IContainerRegistry)a.Container;
    3. c.RegisterSingleton();

    这里其实还有一种更简单的写法:

    (IContainerRegistry)ContainerLocator.Container  这个和上面的c是等价的!

    当一个接口有多个实现类时如何注册?

    我们直接这么写会怎样?

    这样的话,第二个会覆盖第一个,也就是自动注入时,会注入SpectrumMini,而不是SpectrumMini。那该怎么办?那就加个名字!!

    再次运行发现直接报错了!

     因为此时,自动注入懵逼了。有了名字它不知道具体应该注入哪个了。

    我们先换一种思路,不通过属性注入,而是通过容器去拿:

    1. var app = (System.Windows.Application.Current as App).Container;
    2. spectrum = app.Resolve("Mini");
    3. Console.WriteLine(spectrum.GetType().ToString());
    4. spectrum = app.Resolve("Flame");
    5. Console.WriteLine(spectrum.GetType().ToString());

     带上这个名字就好了,不会报错了!

    但是回过头看自动注入,就不行了吗?我网上找了一圈也没找到。突然直觉告诉我,我可以这么试试:

    果然,这样也是可以的,非常完美~~~~

  • 相关阅读:
    React 状态管理 - Mobx 入门(下)接入实战
    SpringBoot多线程环境下,解决多个定时器冲突问题(荣耀典藏版)
    k8s之ConfigMap和Secret
    【STM32】TIM2的PWM:脉冲宽度调制
    21-SpringSecurity
    自满型性格分析,如何改变自满型性格?
    2022第五空间WEB&MISC
    网站降权的康复办法(详解百度SEO数据分析)
    Redis系列:使用Redis实现缓存及相关问题
    [LeetCode解题报告] 241. 为运算表达式设计优先级
  • 原文地址:https://blog.csdn.net/songhuangong123/article/details/126427851