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标题

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言 unity的框架,除了各大公司自己内部使用的,开源并好用的实际并不是很多,我会慢慢挖掘,依次写出自己的一点见解,错误的地方,望各路大神指正。 一、基本概念 控制反转(Inversion of Control,英文缩写为IOC),我的理解就是,原本A类要获取B类的对象,需要你在A类中自己New一个对象,那么是由A来获取并控制B的对象,IOC就是把对象获取的这个过程交给容器依赖注入来处理,A类并不知道B的对象是哪里来的,对B对象的控制,由自己变成了其他类,官方一点的概念可以百度,这个还是蛮多的。 二、StrangeIOC基础类型 实际要理解一个框架的类型,还是要自己看源码,这里我只说一下几个重要类型的作用,这个看源码的时候有个印象,也方便理解,而且说这部分的帖子也很多,我就不再赘述了。 1.Context 上下文组件定义程序边界,也就是可以把一个程序定义成多上下文,让代码更加模块化 它提供了程序入口,也算是框架中耦合度最高的地方 2.Binder和Binding 这两个类是这个框架最重要的组成部分 Binding存储了对象的绑定关系,而Binder存储了Binding的对象 3.View和Mediator MVCS中的View层,View只用于显示,也就是View只负责管理UI,Mediator负责界面逻辑,事件响应等 4.Model MVCS中的Model层,负责数据部分 5.Command MVCS中的Control层,负责执行逻辑代码 6.Service MVCS中的Service层,负责与第三方交互,这个Service我理解的,并不是一定指代服务器,也可以是其他的软件,什么都可以,它就是我们程序对外的接口 7.Dispatcher 派发器是框架内通信主线的其中一种,用来派发消息,触发命令,从而进一步解耦 8.Signal 信号是框架内另外一种通信主线,它采用强类型,来绑定信号和命令之间的关系,实现消息响应的触发 9.ReflectionBinder 反射部分,通过binding来获取类的信息,存储在ReflectedClass中 10.injector 注入器,通过反射获取的信息,来实例化请求的对象 --------------------- 作者:蓝天小僧 来源:CSDN 原文:https://blog.csdn.net/zcaixzy5211314/article/details/80876228 版权声明:本文为博主原创文章,转载请附上博文链接!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值