参考博客地址:
Unity系列文章,推荐:http://www.cnblogs.com/qqlin/archive/2012/10/16/2717964.html
https://www.cnblogs.com/lyps/p/10560256.html
这篇文章主要介绍.NET Framework下面的IOC以及Unity的使用,下一篇文章介绍.NET Core下面自带的容器IServiceCollection以及Autofac的使用https://www.cnblogs.com/taotaozhuanyong/p/11562184.html
IOC(Inverse of Control),控制反转。
说到IOC,就不得不提DI(Dependency Injection),依赖注入
IOC是目标效果,需要DI依赖注入的手段。
分层架构时这些是必须的,可以划分边界独立演化,也方便分工,促进代码复用。。
依赖倒置原则DIP:
系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖。依赖抽象而不是依赖细节。在A勒种调用了B类,A类就是高层,B类就是低层。
面向抽象:
1、一个方法满足多种类型
2、支持下层的扩展。
下面有三种创建一个对象的方式:
AndroidPhone phone = new AndroidPhone();//1 全是细节 IPhone phone = new AndroidPhone();//2 左边抽象右边细节 IPhone phone = ObjectFactory.CreatePhone();//3 封装转移
/// <summary> /// 简单工厂+配置文件+反射 /// </summary> public class ObjectFactory { public static IPhone CreatePhone() { string classModule = ConfigurationManager.AppSettings["iPhoneType"]; Assembly assemly = Assembly.Load(classModule.Split(',')[1]); Type type = assemly.GetType(classModule.Split(',')[0]); return (IPhone)Activator.CreateInstance(type);//无参数构造函数 } public static IPhone CreatePhone(IBaseBll iBLL) { string classModule = ConfigurationManager.AppSettings["iPhoneType"]; Assembly assemly = Assembly.Load(classModule.Split(',')[1]); Type type = assemly.GetType(classModule.Split(',')[0]); return (IPhone)Activator.CreateInstance(type, new object[] { iBLL }); } }
在App.config下面配置节点:
<appSettings> <add key="iPhoneType" value="Bingle.Service.AndroidPhone,Bingle.Service" /> </appSettings>
只有抽象,没有细节,好处是可扩展。
IOC控制反转:
传统开发,上端依赖(调用/指定)下端对象,这个样子会有依赖。控制反转就是把对下端对象的依赖转移到第三方容器(工厂+配置文件+反射),能够让程序拥有更好的扩展性。
下面出现一个问题:
构造A对象,但是A依赖于B对象,那就先构造B,如果B又依赖C,再构造C。。。。。。
IDAL.IBaseDAL baseDAL = new DAL.BaseDAL(); IBLL.IBaseBll baseBll = new BLL.BaseBll(baseDAL); IPhone phone = ObjectFactory.CreatePhone(baseBll);
现在这个问题已经暴露了,下面开始了DI,依赖注入,就能做到构造某个对象时,将依赖的对象自动初始化并注入。
IOC是目标效果,需要DI依赖注入的手段。
DI依赖注入:
三种方式注入:构造函数注入、属性注入、方法注入(按照时间顺序)
[Dependency]//属性注入
[Dependency]//属性注入 public IMicrophone iMicrophone { get; set; }
[InjectionConstructor]//构造函数注入,默认找参数最多的构造函数,方法注入不加这个特性也是可以的,可以不用特性,可以去掉对容器的依赖
[InjectionConstructor]//构造函数注入:默认找参数最多的构造函数 public ApplePhoneUpdate(IHeadphone headphone) { this.iHeadphone = headphone; Console.WriteLine("{0} 带参数构造函数", this.GetType().Name); }
[InjectionMethod]//方法注入
[InjectionMethod]//方法注入 public void Init(IPower power) { this.iPower = power; }
如何使用Unity容器?
1、安装Unity
2、容器三部曲:
实例化容器、注册类型、获取实例
3、项目版本和服务处的版本要一直。
下面是Iphone与AndroidPhone的定义:
public interface IPhone { void Call(); IMicrophone iMicrophone { get; set; } IHeadphone iHeadphone { get; set; } IPower iPower { get; set; } } 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); ; } }