IOC

IOC

IOC全称Inversion of Control,翻译过来就是控制反转,是面向对象编程的一种设计原则,用来降低代码之间的耦合度。它通过将对象的创建和依赖关系的管理交给容器来实现松耦合。这样,组件就可以更加独立,并且可以通过在容器中注册来被其他组件使用。 

IoC 容器通常会提供依赖注入 (Dependency Injection, DI) 的功能,帮助开发者实现依赖管理。通过依赖注入,组件可以在运行时获取所需的依赖,而无需自己创建或管理它们。

应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向。而这就是控制反转的思想。

其实简单工厂模式+配置文件就是一个IOC容器 

 DI

全称Dependency Injection,即依赖注入,是实现IOC这个目标的其中一种设计方法

依赖注入的三种方式

 Unity

 是微软推出的IOC框架,使用这个框架,可以实现AOP面向切面编程,便于代码的后期维护,此外,这套框架还自带单例模式,可以提高程序的运行效率。

项目中什么时候会使用Unity呢,总结分析得到如下情况:

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

使用Unity的好处:

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

首先是需要引入相关的dll

 下面是最简单的一个示例,无参的构造注入:

                  #region 这是一个最简单的例子,其中注册对象这一步还是非常的细节
                    //创建一个Untiy容器 实际上就是创建的一个工厂
                    IUnityContainer unityContainer = new UnityContainer(); //工厂
                    //注册对象 因为要知道创建的是哪个对象
                    unityContainer.RegisterType<IPhone, AndroidPhone>();
                    //获取注册对象的实例 这时候phone就是AndroidPhone的对象
                    IPhone phone = unityContainer.Resolve<IPhone>();
                    #endregion

IPone.cs:

   public interface IPhone
    {
        void Call();
        IMicrophone iMicrophone { get; set; }
        IHeadphone iHeadphone { get; set; }
        IPower iPower { get; set; }
    }

AndroidPhone.cs:

   public class AndroidPhone : IPhone
    {
        public IMicrophone iMicrophone { get; set; }
        public IHeadphone iHeadphone { get; set; }
        public IPower iPower { get; set; }

        public AndroidPhone()
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }

        public AndroidPhone(AbstractPad pad, IHeadphone headphone)
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }

        //[ElevenInjectionConstructor]
        public AndroidPhone(AbstractPad pad)
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }
        public AndroidPhone(IBaseBll baseBll)
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }

        public void Call()
        {
            Console.WriteLine("{0}打电话", this.GetType().Name); ;
        }
    }

结果:

 示例2:

[InjectionMethod]:这个特性代表方法注入

[InjectionConstructor]:代表构造函数的注入,一般默认找参数最多的构造函数,添加这个特性之后就会走添加的构造函数了,如果多个构造函数添加,还是默认找参数最多的

[Dependency]:属性注入,添加这个特性,就算是不在构造函数中对其赋值,只要注册了对应的对象,就会默认赋值

下面是用的示例,

ApplePhone.cs:

 public class ApplePhone : IPhone
    { 
        [Dependency] //
        public IMicrophone iMicrophone { get; set; }
        public IHeadphone iHeadphone { get; set; }
        public IPower iPower { get; set; }

        //public ApplePhone()
        //{
        //    Console.WriteLine("{0}构造函数", this.GetType().Name);
        //}

        //   
        /// <summary>
        /// 构造函数注入:默认找参数最多的构造函数
        /// </summary>
        /// <param name="headphone"></param>
        /// <param name="power"></param>
        /// <param name="headphone1"></param> 
        public ApplePhone(IHeadphone headphone,IPower power,IHeadphone headphone1)
        {
            // 虽然没有iMicrophone赋值,但是因为这个属性加了  [Dependency]特性,所以会自动为其赋值。
            this.iHeadphone = headphone;
            Console.WriteLine("{0}带参数构造函数", this.GetType().Name);
        }

       // [InjectionConstructor] //添加了这个特性,就不会走参数最多的构造函数,而是走这个。
        public ApplePhone(IHeadphone headphone, IPower power)
        {
            this.iHeadphone = headphone;
            Console.WriteLine("{0}带参数构造函数", this.GetType().Name);
        }

        public void Call()
        {
            Console.WriteLine("{0}打电话", this.GetType().Name); ;
        }

        //[InjectionMethod]//方法注入 不加这个特性,是不会走这个方法的。
        public void Init1234(IPower power)
        {
            this.iPower = power;
        }
    }

调用示例:

{
                    // 注意,因为ApplePhone类中用到了下面IMicrophone,IPower等类,所以一定要一次性全部注册齐全,否则报错
                    IUnityContainer unityContainer = new UnityContainer(); //工厂 
                    unityContainer.RegisterType<IPower, Power>();  //注册对象
                    unityContainer.RegisterType<IBaseBll, BaseBll>();
                    unityContainer.RegisterType<IHeadphone, Headphone>();
                    unityContainer.RegisterType<IMicrophone, Microphone>();
                    unityContainer.RegisterType<IPhone, ApplePhone>();
                    //获取对象的实例
                    IPhone phone = unityContainer.Resolve<IPhone>();
                }

如下,因为Init1234方法没有加方法注入的特性,所以在调用Resolve方法的时候没有走,而且iPower属性也没有添加属性注入的特性,构造函数中也没有为它赋值,所以为null

 

 

 

 

 

 

 

 

 

 

 

 

 

1

posted @ 2023-05-14 20:39  安静点--  阅读(23)  评论(0编辑  收藏  举报