WPF入门到跪下 第十一章 Prism(五)IOC的依赖注入

2024-01-31 17:04

本文主要是介绍WPF入门到跪下 第十一章 Prism(五)IOC的依赖注入,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

IOC的依赖注入

一、构造函数方式的依赖注入

以项目启动时MainWindowViewModel的依赖注入为例,默认情况下Prism框架的项目,在打开窗口时会自动匹配主窗口的视图模型类(PrismApplication启动),这里是MainWindowViewModel,匹配到之后Container自动创建MainWindowViewModel的实例,创建时会先检查MainWindowViewModel有没有无参构造函数,如果没有则会检查构造函数的参数类型,并在Container内部列表中寻找对应类型并创建参数对象,然后使用该参数对象来创建MainWindowViewModel。

设置好PrismApplication启动方式后,做以下处理实现IOC的构造函数依赖注入:

  • 创建业务接口及实现类

    public interface IDataAccessBase
    {DataTable GetDatas(string condition);
    }public class DataAccess : IDataAccessBase
    {public DataTable GetDatas(string condition){//做数据访问业务return null;}
    }
    
  • MainWindowViewModel的构造函数中传入所依赖的接口类型

    public class MainWindowViewModel
    {public MainWindowViewModel(IDataAccessBase dataAccess){var data = dataAccess.GetDatas("模拟一下");}
    }
    
  • 类型注册

    RegisterTypes函数中注册依赖类型

    public partial class App : PrismApplication
    {......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IDataAccessBase, DataAccess>();}
    }
    

二、特性方式的依赖注入

注意,特性方式的注入时机要比构造函数方式的注入时机晚,因此如果需要在对象构造时使用依赖对象的话,最好用构造函数依赖注入的方式。

  • 类型注册

    RegisterTypes函数中注册依赖类型

    public partial class App : PrismApplication
    {......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IDataAccessBase, DataAccess>();}
    }
    
  • 特性标注

    使用Prism.Unity命名空间下的Dependency标注属性成员,Prism框架会从IOC容器中寻找对应的类型并注入到属性中。如果在IOC容器中找不到,则会报错。

    public class MainWindowViewModel
    {[Dependency]public IDataAccessBase DataAccess{ get; set; }
    }
    

三、注册&注入已经存在的实例对象

有些情况下希望直接将一个已经存在的实例对象注册到IOC容器中;或者某个接口只返回接口类型的对象时,无法通过接口+实现类的方式注册到IOC容器中,只能先创建该实例对象,然后将实例对象注册到IOC容器中(例如Log4net)。这个时候可以使用IContainerRegistry对象的RegisterInstance方法。

1、注册

public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterInstance(LogManager.GetLogger("Test"));//可以指定名称//containerRegistry.RegisterInstance(LogManager.GetLogger("Test"), TestLog);}
}

2、注入

注入方式,跟上文的一样,可以通过特性或者构造参数。

需要注意的是,如果指定了名称,就只能通过特性指定名称注入或者使用IUnityContainerIContainerExtension对象实例来获取了。

public MainWindow(ILog log)
{InitializeComponent();log.Error("错误", new Exception("发生了一个异常"));//错误log.Fatal("严重错误", new Exception("发生了一个致命错误"));//严重错误log.Info("信息"); //记录一般信息log.Debug("调试信息");//记录调试信息log.Warn("警告");//记录警告信息
}

IUnityContainer

一、获取注册信息

IUnityContainer接口的实例中存放了IOC容器中的注册信息,其中包括Prism框架默认注册的以及我们自己注册的。

以下为常用的三种注册方式后,IUnityContainer实例中存放注册信息的不同状态。

注册接口与类型,没有设置名称

public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<ITestClass, TestClass>();}
}

在这里插入图片描述

注册接口与类型,并设置名称

public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<ITestClass, TestClass>("TestClassName");}
}

在这里插入图片描述

直接注册类型

public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<TestClass>();}
}

在这里插入图片描述

不同的注册方式会导致注册信息的状态有所不同,其中导航、视图、类型的注册根据不同情况也有所不同,在实际开发过程中可以先监控一下IUnityContainer实例中的注册信息再根据实际情况来使用。

需要注意的是,如果在注册过程中设置了name属性,那么在向容器中获取对象时,也要使用对应的name来获取,如果还使用类名来获取,会直接报错。

二、从容器中获取对象

除了能在IUnityContainer实例中获取到IOC容器的注册信息外,还能通过实例方法Resolve<T>()从容器中获取指定的依赖对象。
此外,从IContainerProvider实例的Resolve<T>()方法中也可以从容器中获取指定的依赖对象。

public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterSingleton<ITestClass, TestClass>();}
}
public class MainWindowViewModel
{public MainWindowViewModel(IUnityContainer unityContainer,  IContainerProvider containerProvider){var a = unityContainer.Resolve<ITestClass>();var b = containerProvider.Resolve<ITestClass>();var result = a == b;	//true}
}

三、实例-Region中删除指定视图

public class FileUploadViewModel:BindableBase
{//页签关闭命令public ICommand CloseCommand { get; set; }public FileUploadViewModel(IRegionManager regionManager, IUnityContainer unityContainer){CloseCommand = new DelegateCommand<string>(uri =>{//从IUnityContainer 实例中获取指定的注册信息对象var obj = unityContainer.Registrations.Where(r => r.Name == uri || r.MappedToType == Type.GetType("FileUploadView")).FirstOrDefault();var name = obj?.MappedToType.Name;if (!string.IsNullOrEmpty(name)){var region = regionManager.Regions["MainViewRegion"];var view = region.Views.Where(v=> v.GetType().Name == name).FirstOrDefault();if (view != null)region.Remove(view);}});}
}

IContainerExtension

Prism的IOC容器中默认注册的还有IContainerExtension接口,该接口实现了IContainerProviderIContainerRegistry接口,因此其实现类的实例对象同时具有注册和从容器中获取对象的功能,如果希望在App类中的RegisterTypes方法之外的地方向容器注册的话,可以通过IContainerExtension的实例对象来完成。

public class MainWindowViewModel
{public MainWindowViewModel(IUnityContainer unityContainer,  IContainerExtension containerProvider){containerProvider.Register<TestClass>();var test = containerProvider.Resolve<TestClass>();}
}

这篇关于WPF入门到跪下 第十一章 Prism(五)IOC的依赖注入的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/664455

相关文章

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM

IDEA Maven提示:未解析的依赖项的问题及解决

《IDEAMaven提示:未解析的依赖项的问题及解决》:本文主要介绍IDEAMaven提示:未解析的依赖项的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录IDEA Maven提示:未解析的依编程赖项例如总结IDEA Maven提示:未解析的依赖项例如

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE

Python pip下载包及所有依赖到指定文件夹的步骤说明

《Pythonpip下载包及所有依赖到指定文件夹的步骤说明》为了方便开发和部署,我们常常需要将Python项目所依赖的第三方包导出到本地文件夹中,:本文主要介绍Pythonpip下载包及所有依... 目录步骤说明命令格式示例参数说明离线安装方法注意事项总结要使用pip下载包及其所有依赖到指定文件夹,请按照以

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb