场景举例:我们使用手机打电话的时候,我记不住电话号码,所以需要先打开电话本,因为手机没有电了,所以需要再给手机充上电,我习惯戴上耳机打电话,所以最后要戴上耳机打电话
也就是说在这个场景下:构造手机对象的时候,手机对象依赖于电话本对象,同时依赖于充电器对象,同时也依赖于耳机对象。
1、手机接口
手机接口,里面有两个方法,一个是打电话,一个是其他方式打电话
namespace David.General.EF.Bussiness.Interface { public interface IPhoneService { /// <summary> /// 打电话 /// </summary> void Call(); /// <summary> /// 其他方式打电话 /// </summary> /// <param name="iEarphoneService"></param> void OtherCall(IEarphoneService iEarphoneService); } }
2、电话本接口
电话本接口,里面有一个打开电话本方法
namespace David.General.EF.Bussiness.Interface { public interface IPhoneBookService { /// <summary> /// 打开电话本 /// </summary> void Open(); } }
3、电源接口
电源接口,里面有一个充电方法
namespace David.General.EF.Bussiness.Interface { public interface IPowerService { /// <summary> /// 充电 /// </summary> void ChargeBattery(); } }
4、耳机接口
耳机接口,里面有一个戴上耳机方法
namespace David.General.EF.Bussiness.Interface { public interface IEarphoneService { /// <summary> /// 戴上耳机 /// </summary> void PutOn(); } }
1、手机接口实现
namespace David.General.EF.Bussiness.Service { public class ApplePhoneService : IPhoneService { public IPowerService IPowerService { get; set; } [Dependency]//属性注入 public IPhoneBookService IPhoneBookService { get; set; } public ApplePhoneService(IPowerService iPowerService) { IPowerService = iPowerService; } /// <summary> /// 打电话 /// </summary> public void Call() { IPhoneBookService.Open(); IPowerService.ChargeBattery(); Console.WriteLine($"{nameof(ApplePhoneService)}打电话"); } //方法注入 [InjectionMethod] public void OtherCall(IEarphoneService earphoneService) { IPhoneBookService.Open(); IPowerService.ChargeBattery(); earphoneService.PutOn(); Console.WriteLine($"{nameof(ApplePhoneService)}打电话"); } } }
2、电话本接口实现
namespace David.General.EF.Bussiness.Service { public class PhoneBookService : IPhoneBookService { /// <summary> /// 打开电话本 /// </summary> public void Open() { Console.WriteLine($"{nameof(PhoneBookService)}打开电话本"); } } }
3、电源接口实现
namespace David.General.EF.Bussiness.Service { public class ApplePowerService : IPowerService { /// <summary> /// 充电 /// </summary> public void ChargeBattery() { Console.WriteLine($"{nameof(ApplePowerService)}充电"); } } }
4、耳机接口实现
namespace David.General.EF.Bussiness.Service { public class EarphoneService : IEarphoneService { /// <summary> /// 戴上耳机 /// </summary> public void PutOn() { Console.WriteLine($"{nameof(EarphoneService)}戴上耳机"); } } }
namespace David.General.EF.Test.IOCTest { public class UnityTest { public static void Show() { //1、实例化容器 IUnityContainer container = new UnityContainer();// //2、注册类型,但凡要用的类型,都需要注册,否则容器怎么工作呢 container.RegisterType<IPhoneService, ApplePhoneService>(); container.RegisterType<IPowerService, ApplePowerService>(); container.RegisterType<IPhoneBookService, PhoneBookService>(); container.RegisterType<IEarphoneService, EarphoneService>(); //3、获取实例 IPhoneService iPhone = container.Resolve<IPhoneService>(); } } }
1、在构造ApplePhoneService的时候,先去构造了ApplePowerService,也就是先构造了电源对象

2、在构造完ApplePhoneService后,又紧跟着构造了PhoneBookService,也就是构造了电话本对象,因为构造顺序是构造函数注入--属性注入--方法注入

3、在构造完PhoneBookService后,最后构造了EarphoneService,我们在调用的时候没有主动去调用OtherCall方法,但是因为OtherCall标记了InjectionMethod特性,所以会注入方法的依赖对象,也就同时会调用该方法


注册类型的时候:没有抽象实现不行,没有父子关系不行,但凡要用的类型,都需要注册,否则容器怎么工作呢
为什么要标记特性:因为那么多属性,那么多构造函数,容器怎么知道要构造哪一个呢,所以需要特性标记一下
构造函数比较特殊:特殊在就算没有标记特性,容器默认构造找参数最多的构造函数,可以不用特性,不用特性意味着可以去掉对容器的依赖
原文:https://www.cnblogs.com/menglin2010/p/12558253.html