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

IOC容器:Unity

IOC简介:

什么是IOC

学习IOC之前先来了解一个依赖倒置原则(DIP),依赖倒置原则是IOC的核心原理。

依赖导致:即上层模块不应该依赖于低层模块,二者应该通过抽象来依赖。依赖于抽象,而不是依赖于细节。

IOC(Inversion of Control), 控制反转

DI (Dependency Injection),依赖注入

IOC的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。

那就究竟什么是IOC呢?

IOC(Inversion of Control)即控制反转,是一个重要的面向对象编程的法则来消减程序之间的耦合问题,把程序中上层对下层依赖,转移到一个第三方容器中来装配。IOC是程序设计的目标,实现方式包含依赖注入和依赖查找,在.net中只有依赖注入。

说到IOC,就不能不说DI。

DI:即依赖注入,是IOC的实现手段。

有以下优点:

  • 1.简化了对象的创建,特别是针对分层对象结构和依赖关系;
  • 2.需求的抽象,允许开发人员在运行时或配置文件中指定依赖关系,简化横切关注点的管理;
  • 3.推迟为容器配置组件的时机,增加了灵活性;
  • 4.服务定位能力,这使客户能够存储或缓存容器;
  • 5.实例和类型拦截
     

unity能够做什么呢,列举部分如下:

1.Unity支持简单对象创建,特别是分层对象结构和依赖,以简化程序代码。其包含一个编译那些可能存在依赖于其他对象的对象实例机制。
2.Unity支持必要的抽象,其允许开发者在运行时或配置去指定依赖关系同时可以简单的管理横切点(AOP)。
3.Unity增加了推迟到容器组件配置的灵活性。其同样支持一个容器层次的结构。
4.Unity拥有服务定位能力,对于一个程序在许多情况下重复使用组件来分离和集中功能是非常有用的。
5.Unity允许客户端储存或缓存容器。对于在ASP.NET Web applications中开发者将容器持久化于ASP.NET中的session或application中特别有效。
6.Unity拥有拦截能力,其允许开发者通过创建并执行handlers(在方法或属性被调用到达之前)来为已存在的组件增加一个函数,并再次为返回调用结果。
7.Unity可以从标准配置系统中读取配置信息,例如:XML文件,同时使用配置文件来配置容器。
8.Unity支持开发者实现自定义容器扩展,例如:你可以实现方法来允许额外的对象构造和容器特征,例如缓存。
9.Unity允许架构师和开发者在现代化的程序中更简单的实现通用设计模式。

什么情况下要使用unity呢?

1.所构建的系统依赖于健全的面向对象原则,但是大量不同的代码交织在一起而难以维护。
2.构建的对象和类需要依赖其他对象或类。
3.依赖于复杂的或需要抽象的对象。
4.希望利用构造函数、方法或属性的调用注入优势。
5.希望管理对象实例的生命周期。
6.希望能够在运行时管理并改变依赖关系。
7.希望在拦截方法或属性调用的时候生成一个策略链或管道处理容器来实现横切(AOP)任务。
8.希望在Web Application中的回发操作时能够缓存或持久化依赖关系。

注意

先执行构造函数注入,在执行属性注入,最后执行方法注入。

注意:这个一个单独的配置文件,要把属性里面的复制到输出目录改为始终复制,那么这个配置文件才会生成到Debug目录里面。

如果改成使用配置文件的方式实现的话,代码里面就不会依赖于细节了,只要一个接口类型。既然没有细节了,那么对项目进行如下的改造:把引用里面对细节的引用都去掉,然后Debug文件夹里面没有这两个DLL了,但是这时需要把这两个DLL复制到Debug目录下面,否则程序运行的时候会找不到具体实现的类型。这样就意味着程序架构只依赖于接口。

引用里面只要对接口的引用了,没有对具体实现的引用。去掉了对细节的依赖。

注意:使用配置文件实现时,必须把接口的具体实现类复制到程序目录下面。

如果有额外添加了一种数据库,那么只需要修改配置文件,把新的实现类复制到程序目录下面即可实现程序的升级。

简单例子:

 

    public interface IA { }
    public interface IB { }
    public interface IC { }
    public interface ID { }

    public class A : IA
    {
        public IB B { get; set; }
        [Dependency]
        public IC C { get; set; }
        public ID D { get; set; }

        public A(IB b)
        {
            this.B = b;
            Console.WriteLine("A");
        }
        [InjectionMethod]
        public void Initialize(ID d)
        {
            this.D = d;
        }
    }
    public class AA : IA
    {
        public IB B { get; set; }
        [Dependency]
        public IC C { get; set; }
        public ID D { get; set; }

        public AA(IB b)
        {
            this.B = b;
            Console.WriteLine("AA");
        }
        [InjectionMethod]
        public void Initialize(ID d)
        {
            this.D = d;
        }
    }
    public class B : IB { }
    public class C : IC { }
    public class D : ID { }

代码方式注册:

        static void Main(string[] args)
        { 
            string configFile = "Unity.config";
            var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile }; 
            //从config文件中读取配置信息
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            //获取指定名称的配置节
            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
            IUnityContainer container = new UnityContainer();
            section.Configure(container);
            A a = (A)container.Resolve<IA>("A");
            AA aa = (AA)container.Resolve<IA>("AA");

            Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No");
            Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No");
            Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No");

            Console.Read();
        }

 

配置文件方式注册:

        static void Main(string[] args)
        {
            IUnityContainer container = new UnityContainer(); //注册映射   
            container.RegisterType<IA, A>();
            container.RegisterType<IB, B>();
            container.RegisterType<IC, C>();
            container.RegisterType<ID, D>();

            //得到A的实例  
            A a = (A)container.Resolve<IA>();

            Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No");
            Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No");
            Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No");

            Console.Read();
        }

配置文件内容:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
  </configSections>
  <unity>
    <containers>
      <container>
        <!--逗号前面是接口类型的完全限定名:命名空间+接口名称,逗号后面是DLL文件的名称 name解决同一个接口不同实例问题-->
        <register type="ConsoleApplicationMain.IA, ConsoleApplicationMain" mapTo="ConsoleApplicationMain.A, ConsoleApplicationMain" name="A"/>
        <register type="ConsoleApplicationMain.IA, ConsoleApplicationMain" mapTo="ConsoleApplicationMain.AA, ConsoleApplicationMain" name="AA"/>
        <register type="ConsoleApplicationMain.IB, ConsoleApplicationMain" mapTo="ConsoleApplicationMain.B, ConsoleApplicationMain"/>
        <register type="ConsoleApplicationMain.IC, ConsoleApplicationMain" mapTo="ConsoleApplicationMain.C, ConsoleApplicationMain"/>
        <register type="ConsoleApplicationMain.ID, ConsoleApplicationMain" mapTo="ConsoleApplicationMain.D, ConsoleApplicationMain"/>
      </container>
    </containers>
  </unity>
</configuration>
<!-- 注意:这个一个单独的配置文件,要把属性里面的复制到输出目录改为始终复制,那么这个配置文件才会生成到Debug目录里面。-->

 

参考资料:

IOC容器:Unity
https://www.cnblogs.com/dotnet261010/p/9054201.html
Unity Ioc框架简单例子
https://www.cnblogs.com/dragon-L/p/5124872.html
.NET Unity IOC框架使用实例
https://www.cnblogs.com/pengdylan/p/6371724.html?utm_source=itdadao&utm_medium=referral
依赖注入的三种实现
https://www.cnblogs.com/sylone/p/9479276.html

Demo:

我做了两个demo,一个是简单demo,一个是完整demo;

下载地址:下载源码

 

1标题
2标题

 

相关文章:

  • 依赖注入 与 抽象工厂
  • C#获取硬盘序列号,CPU序列号,网卡MAC地址
  • mysql 表分区设置
  • mysql复制表结构和表数据
  • 健忘者系列-MVC图片上传(一)
  • 健忘者系列-MVC图片上传(二)
  • mybatis-plus 代码生成器使用
  • java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to ***
  • you *might* want to use the less safe log_bin_trust_function_creators variable
  • node.js websocket.io 搭建 websocket 通信服务
  • Mysql 定时器
  • mysql 存储过程 遍历
  • mysql复制表结构的几种方式
  • TO_CHAR 和 TO_DATE的一些用法
  • Spark:学习笔记
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Laravel Mix运行时关于es2015报错解决方案
  • Linux Process Manage
  • Linux后台研发超实用命令总结
  • Mysql优化
  • NSTimer学习笔记
  • opencv python Meanshift 和 Camshift
  • springMvc学习笔记(2)
  • SpriteKit 技巧之添加背景图片
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 数据可视化之 Sankey 桑基图的实现
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (13):Silverlight 2 数据与通信之WebRequest
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (九)信息融合方式简介
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)winform之ListView
  • .Net mvc总结
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .NET构架之我见
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .ui文件相关
  • :如何用SQL脚本保存存储过程返回的结果集
  • @property括号内属性讲解
  • [1525]字符统计2 (哈希)SDUT
  • [Android] Implementation vs API dependency
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测
  • [C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)
  • [Json.net]快速入门
  • [Linux] Boot分区满了的处理方法 The volume boot has only 0 bytes disk space remaining
  • [MFC] MFC 获取指定窗口截图(大小可调)