• Ioc 之 Unity的依赖注入


      Unity是微软官方提供的一个Ioc容器,用来实现依赖注入,减少代码之间的耦合程度。使用Unity实现Ioc方式有两种,一种是使用代码方式实现,一种是利用配置文件来实现。

      我们先来看一下代码方式是如何实现的。我们先定义 IPay接口,IOrder接口,再定义WeChatPay,AliPay,Order三个类。

       /// <summary>
        /// 支付接口
        /// </summary>
        public interface IPay
        {
            string Pay();
        }
    
        public interface IOrder
        {
            string ToPay();
        }
        /// <summary>
        /// 微信支付
        /// </summary>
        public class WeChatPay :IPay
        {
            public string Pay()
            {
                return "微信支付";
            }
        }
        /// <summary>
        /// 支付宝支付
        /// </summary>
        public class AliPay : IPay
        {
            public string Pay()
            {
                return "支付宝支付";
            }
        }
    /// <summary>
        /// 订单
        /// </summary>
        public class Order : IOrder
        {
            /// <summary>
            /// 订单支付方式
            /// </summary>
            public IPay _iPay;
    
            //构造函数注入:可以不写,因为Unity解析时默认会找参数最多的构造函数
            [InjectionConstructor]
            public Order(IPay iPay)
            {
                _iPay = iPay;
            }
    
            [Dependency]//属性注入
            public IPay _iPayProperty { get; set; }
    
    
            [InjectionMethod]//方法注入
            public void PayInit(IPay ipay)
            {
                this._iPay = ipay;
            }
    
            public string ToPay()
            {
                return this._iPay.Pay();
            }
        }

      接着,我们可以使用代码的方式来使用Unity

     //创建一个Unity空容器
     IUnityContainer container = new UnityContainer();
    
     //向Unity容器注入WeChatPay
     container.RegisterType<IPay, WeChatPay>();
     //向Unity容器注入AliPay,使用命名注册,解析的时候也需要使用命名获取实例
     container.RegisterType<IPay, AliPay>("alipay"); 
    
     var obj = container.Resolve<IPay>();
     Console.WriteLine(obj.Pay());
     obj = container.Resolve<IPay>("alipay");
     Console.WriteLine(obj.Pay());
    
     container.RegisterType<IOrder, Order>();
     //Unity解析的时候会按照:构造函数注入 --> 属性注入  --> 方法注入的顺序进行解析
     var order = container.Resolve<IOrder>();
     Console.WriteLine($"Order.ToPay: {order.ToPay()}");
     
    Console.ReadLine();

      运行得到结果

      那么,Unity注入类型的生命周期有哪些呢?

    //生命周期
    IUnityContainer container = new UnityContainer();
    
    //默认瞬时,每一次都是全新生成
    container.RegisterType<IOrder, Order>();
    container.RegisterType<IOrder, Order>(new TransientLifetimeManager());
    
    //容器单例
    container.RegisterType<IOrder, Order>(new ContainerControlledLifetimeManager());
    
    //线程单例
    container.RegisterType<IOrder, Order>(new PerThreadLifetimeManager());
    var phone1 = container.Resolve<IPhone>();
    var phone2 = container.Resolve<IPhone>();
    Console.WriteLine(object.ReferenceEquals(phone1, phone2)); //结果为true
    
    //分级容器单例
    container.RegisterType<IOrder, Order>(new HierarchicalLifetimeManager());
    IUnityContainer childContainer = container.CreateChildContainer();
    
    //外部可释放单例
    container.RegisterType<IOrder, Order>(new ExternallyControlledLifetimeManager());
    
    //循环引用 不推荐
    container.RegisterType<IOrder, Order>(new PerResolveLifetimeManager());

       接下来我们再来看下Unity使用配置文件的方式该如何实现依赖注入。我们在项目中新建一个文件夹Config,然后再创建unity.config文件。

    <configuration>
      <configSections>
        <!--<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>-->
        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
      </configSections>
      <unity>
        <!--<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>-->
        <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
        <containers>
          
          <container name="IocContainer">
            <!-- 格式:类名,程序集名称 -->
            <register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order, IocDemo.Service"/>
            <register type="IocDemo.IService.IPay,IocDemo.IService" mapTo="IocDemo.Service.AliPay, IocDemo.Service" name="alipay"/>
            <register type="IocDemo.IService.IPay, IocDemo.IService" mapTo="IocDemo.Service.WeChatPay, IocDemo.Service"/>
          </container>
        </containers>
      </unity>
    </configuration>

      然后在程序中使用ExeConfigurationFileMap来装载该配置文件

    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Config\unity.config");//找配置文件的路径
    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
    
    IUnityContainer container = new UnityContainer();
    section.Configure(container, "IocContainer");
    
    IOrder order = container.Resolve<IOrder>();
    Console.WriteLine(order.ToPay());
    
    IPay aliPay = container.Resolve<IPay>("alipay");
    Console.WriteLine(aliPay.Pay());
    
    Console.ReadLine();

      我们也可以在配置文件中指定生命周期,构造函数初始值

      <register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order,IocDemo.Service">
         <lifetime type="transient" />
         <constructor>
             <!--<param name="id" type="System.Int32" value="3" />-->
             <param name="iPay" type="IocDemo.IService.IPay,IocDemo.IService"></param>
         </constructor>
      </register>
  • 相关阅读:
    artDialog基本使用
    SQL数据类型(SQL Server六个类型使用)
    常用SQL语句大全(SQL Server)
    从PRISM开始学WPF(八)导航Navigation-更新至Prism7.1
    从PRISM开始学WPF(番外)共享上下文 RegionContext-更新至Prism7.1
    从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator-更新至Prism7.1
    从PRISM开始学WPF(六)MVVM(二)Command-更新至Prism7.1
    从PRISM开始学WPF(四)Prism-Module-更新至Prism7.1
    从PRISM开始学WPF(二)认识Prism-更新至Prism7.1
    从PRISM开始学WPF(一)认识WPF-更新至Prism7.1
  • 原文地址:https://www.cnblogs.com/jesen1315/p/11043840.html
Copyright © 2020-2023  润新知