DIP依赖倒置原则:系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖
依赖抽象,而不是细节
贯彻依赖倒置原则,左边能抽象,右边实例化的时候不能直接用抽象,所以需要借助一个第三方
高层本来是依赖低层,但是可以通过工厂(容器)来决定细节,去掉了对低层的依赖
IOC控制反转:把高层对低层的依赖,转移到第三方决定,避免高层对低层的直接依赖(是一种目的)
那么程序架构就具备良好扩展性和稳定性
DI依赖注入:是用来实现IOC的一种手段,
在构造对象时,可以自动的去初始化,对象需要的对象
构造函数注入 属性注入 方法注入,IOC容器初始化ApplePhone的时候 通过配置文件实例化 属性,方法,构造函数
using Microsoft.Practices.Unity; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ruanmou.Interface; using System; using Unity.Attributes;namespace Ruanmou.Service {public class ApplePhone : IPhone{[Dependency]//属性注入:不错,但是有对容器的依赖public IMicrophone iMicrophone { get; set; }public IHeadphone iHeadphone { get; set; }public IPower iPower { get; set; }//[InjectionConstructor]public ApplePhone(){Console.WriteLine("{0}构造函数", this.GetType().Name);}//[InjectionConstructor]//构造函数注入:最好的,默认找参数最多的构造函数public ApplePhone(IHeadphone headphone){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;}} }
不管是构造对象,还是注入对象,这里都是靠反射做到的
有了依赖注入,才可能做到无限层级的依赖抽象,才能做到控制反转
IOC Unity容器 可以通过代码注册或配置文件注册接口对应实现类,实现了不依赖具体,可以对对象全局单例,线程单例
例子1
Service业务逻辑层升级,在原有1.0的基础上添加一些功能,使用配置文件注册
<container name="testContainer1"><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.ApplePhone, Ruanmou.Service"/><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.AndroidPhone, Ruanmou.Service" name="Android"/><register type="Ruanmou.Interface.IMicrophone, Ruanmou.Interface" mapTo="Ruanmou.Service.Microphone, Ruanmou.Service"/><register type="Ruanmou.Interface.IHeadphone, Ruanmou.Interface" mapTo="Ruanmou.Service.Headphone, Ruanmou.Service"/><register type="Ruanmou.Interface.IPower, Ruanmou.Interface" mapTo="Ruanmou.Service.Power, Ruanmou.Service"/><register type="Ruanmou.IDAL.IBaseDAL, Ruanmou.IDAL" mapTo="Ruamou.DAL.BaseDAL, Ruamou.DAL"/></container><container name="testContainer"><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.AndroidPhone, Ruanmou.Service.Extend"/><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.AndroidPhone, Ruanmou.Service.Extend" name="Android"/><register type="Ruanmou.Interface.IMicrophone, Ruanmou.Interface" mapTo="Ruanmou.Service.Microphone, Ruanmou.Service.Extend"/><register type="Ruanmou.Interface.IHeadphone, Ruanmou.Interface" mapTo="Ruanmou.Service.Headphone, Ruanmou.Service.Extend"/><register type="Ruanmou.Interface.IPower, Ruanmou.Interface" mapTo="Ruanmou.Service.Power, Ruanmou.Service.Extend"/><register type="Ruanmou.IDAL.IBaseDAL, Ruanmou.IDAL" mapTo="Ruamou.DAL.BaseDAL, Ruamou.DAL"/></container>
只需要把服务2.0的类库(实现1.0的原有接口)dll拿过来即可使用,代码不做任何修改
例子2 业务扩展,新加功能
应该是加几个接口和实现类的映射,就可以解决了。
例子3 实现AOP
方法需要加日志,加异常管理,可以不修改原有代码,直接新加异常管理类等的类库,在Unity配置文件添加AOP配置节点即可实现
配置文件配置,
<container name="testContainerAOP"><extension type="Interception"/><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.AndroidPhone, Ruanmou.Service.Extend"><interceptor type="InterfaceInterceptor"/><interceptionBehavior type="Ruanmou.Framework.AOP.AuthorizeBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.SmsBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.ExceptionLoggingBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.CachingBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.LogBeforeBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.ParameterCheckBehavior, Ruanmou.Framework"/><interceptionBehavior type="Ruanmou.Framework.AOP.LogAfterBehavior, Ruanmou.Framework"/></register><register type="Ruanmou.Interface.IPhone,Ruanmou.Interface" mapTo="Ruanmou.Service.AndroidPhone, Ruanmou.Service.Extend" name="Android"/><register type="Ruanmou.Interface.IMicrophone, Ruanmou.Interface" mapTo="Ruanmou.Service.Microphone, Ruanmou.Service.Extend"/><register type="Ruanmou.Interface.IHeadphone, Ruanmou.Interface" mapTo="Ruanmou.Service.Headphone, Ruanmou.Service.Extend"/><register type="Ruanmou.Interface.IPower, Ruanmou.Interface" mapTo="Ruanmou.Service.Power, Ruanmou.Service.Extend"/><register type="Ruanmou.IDAL.IBaseDAL, Ruanmou.IDAL" mapTo="Ruamou.DAL.BaseDAL, Ruamou.DAL"></register></container>
贴一个异常处理的AOP例子代码
namespace Ruanmou.Framework.AOP {public class ExceptionLoggingBehavior : IInterceptionBehavior{public IEnumerable<Type> GetRequiredInterfaces(){return Type.EmptyTypes;}public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext){IMethodReturn methodReturn = getNext()(input, getNext);Console.WriteLine("ExceptionLoggingBehavior");if (methodReturn.Exception == null){Console.WriteLine("无异常");}else{Console.WriteLine($"异常:{methodReturn.Exception.Message}");}return methodReturn;}public bool WillExecute{get { return true; }}} }
例子4 数据访问层的替换,因为已经不依赖具体实现,把配置文件的接口对应的数据访问层实现类替换即可,配置文件格式为InterFace Map 实现类
数据访问层的封装公共增删改查,Unity 管理 EF DBcontext,保持全局或线程单例还没有看到,最近在学内存管理和.Net垃圾回收