内置Unity容器

场景举例:我们使用手机打电话的时候,我记不住电话号码,所以需要先打开电话本,因为手机没有电了,所以需要再给手机充上电,我习惯戴上耳机打电话,所以最后要戴上耳机打电话
也就是说在这个场景下:构造手机对象的时候,手机对象依赖于电话本对象,同时依赖于充电器对象,同时也依赖于耳机对象。

  • 接口

1、手机接口

手机接口,里面有两个方法,一个是打电话,一个是其他方式打电话

namespace David.General.EF.Bussiness.Interface
{
    public interface IPhoneService
    {
        /// 
        /// 打电话
        /// 
        void Call();

        /// 
        /// 其他方式打电话
        /// 
        /// 
        void OtherCall(IEarphoneService iEarphoneService);
    }
}

2、电话本接口

电话本接口,里面有一个打开电话本方法

namespace David.General.EF.Bussiness.Interface
{
    public interface IPhoneBookService
    {
        /// 
        /// 打开电话本
        /// 
        void Open();
    }
}

3、电源接口

电源接口,里面有一个充电方法

namespace David.General.EF.Bussiness.Interface
{
    public interface IPowerService
    {
        /// 
        /// 充电
        /// 
        void ChargeBattery();
    }
}

4、耳机接口
耳机接口,里面有一个戴上耳机方法

namespace David.General.EF.Bussiness.Interface
{
    public interface IEarphoneService
    {
        /// 
        /// 戴上耳机
        /// 
        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;
        }

        /// 
        /// 打电话
        /// 
        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
    {
        /// 
        /// 打开电话本
        /// 
        public void Open()
        {
            Console.WriteLine($"{nameof(PhoneBookService)}打开电话本");
        }
    }
}

3、电源接口实现

namespace David.General.EF.Bussiness.Service
{
    public class ApplePowerService : IPowerService
    {
        /// 
        /// 充电
        /// 
        public void ChargeBattery()
        {
            Console.WriteLine($"{nameof(ApplePowerService)}充电");
        }
    }
}

4、耳机接口实现

namespace David.General.EF.Bussiness.Service
{
    public class EarphoneService : IEarphoneService
    {
        /// 
        /// 戴上耳机
        /// 
        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();
            container.RegisterType();
            container.RegisterType();
            container.RegisterType();
            //3、获取实例
            IPhoneService iPhone = container.Resolve();
        }
    }
}
  • 效果图

1、在构造ApplePhoneService的时候,先去构造了ApplePowerService,也就是先构造了电源对象

内置Unity容器_第1张图片

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

内置Unity容器_第2张图片

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

内置Unity容器_第3张图片

 

内置Unity容器_第4张图片

  • 总结

  注册类型的时候:没有抽象实现不行,没有父子关系不行,但凡要用的类型,都需要注册,否则容器怎么工作呢

  为什么要标记特性:因为那么多属性,那么多构造函数,容器怎么知道要构造哪一个呢,所以需要特性标记一下

  构造函数比较特殊:特殊在就算没有标记特性,容器默认构造找参数最多的构造函数,可以不用特性,不用特性意味着可以去掉对容器的依赖

你可能感兴趣的:(内置Unity容器)