• IOC Unity容器的基本使用


    Unity IOC容器的基本使用

    引入类库

    类库名 作用
    Unity 包含Unity容器和抽象库作为一个单独的包
    Unity.Configuration 配置文件,以配置文件的方式配置Unity容器
    Unity Interception AOP扩展
    Unity.Interception.Configuration AOP配置文件,以配置文件的方式提供AOP扩展

    基本使用

    测试类

    public interface ICar
    {
        int Run();
    }
    
    public class Ford : ICar
    {
        private int _meter = 0;
    
        public int Run()
        {
            return ++_meter;
        }
    }
    
    public class BMW : ICar
    {
        private int _meter = 0;
    
        public int Run()
        {
            return ++_meter;
        }
    }
    
    public class Driver
    {
        private ICar _car = null;
    
        public Driver(ICar car)
        {
            _car = car;
        }
    
        public void RunCar()
        {
            Console.WriteLine($"{_car.GetType().Name}:跑了{_car.Run()} 米 ");
        }
    }
    

    代码方式

    IUnityContainer container = new UnityContainer();
    container.RegisterType<ICar,Ford>();
    
    Driver driver = container.Resolve<Driver>();
    
    driver.RunCar();
    Console.Read();
    

    配置文件方式

    1. 创建CfgFiles专门存放Unity.config

    2. Unity.config的属性设置为始终复制

    3. 设置配置文件,包含了AOP的配置,相关的AOP源码会放在文章下方。

    <configuration>
    	<configSections>
    		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
    	</configSections>
    	<unity>
    		<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    		<containers>
    			<container name="aopContainer">
    				<register type="UnityTest.ICar,UnityTest" mapTo="UnityTest.BMW,UnityTest"/>					
    			</container>
    		</containers>
    	</unity>
    </configuration>
    
    1. 引入Unity容器
    #region 引入Unity容器,这是一段固定写法 作用是读取当前应用程序运行目录下的Unity.Config配置文件,配置一个容器
    //1. 初始化UnityContainer容器
    IUnityContainer container = new UnityContainer();
    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    //2. 开始读取配置文件
    fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\Unity.Config");
    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
    #endregion
    //01 使用UnityConfigurationSection 配置(容器,名称)方法代替  配置容器 将容器和配置文件中的别名关联"
    configSection.Configure(container, "aopContainer");
    //02 通过容器创建对象
    Driver driver = container.Resolve<Driver>();
    //02 调用业务方法
    driver.RunCar();
    Console.Read();
    

    生命周期管理

    瞬时生命周期(TransientLifetimeManager)

    瞬时生命周期,每次都是构造一个新的对象。

    IUnityContainer container = new UnityContainer();
    //以下两种注册,效果是一样的
    //默认瞬时生命周期:每次都是构造一个新的 
    container.RegisterType<ICar, BMW>();
    container.RegisterType<ICar, BMW>(new TransientLifetimeManager());
    
    Driver drv = container.Resolve<Driver>(); 
    

    配置文件

    <register type="ICar" mapTo="BMW">
      <lifetime type="transient" />
    </register>
    

    在配置文件中注册关系的时候更改一个生命周期管理器只需在配置节下新增既可(如果不新增则默认使用TransientLifetimeManager)。

    其中有3个参数:

    1)type,生命期周期管理器的类型,可以选择Unity内置的,也可以使用自定义的,其中内置的生命周期管理器会有智能提示。

    2)typeConverter,生命周期管理器转换类,用户自定义一个生命周期管理器的时候所创建一个转换器。

    3)value,初始化生命周期管理器的值。

    全局单例生命周期(SingletonLifetimeManager)

    1. 全局单例生命周期,全局只有一个该类型示例
    2. 非强制性,只有通过容器获取的才是单例。
    3. 项目中推荐使用容器单例
    container.RegisterType<ICar, Ford>(new SingletonLifetimeManager());
    ICar car = container.Resolve<ICar>();
    ICar car1 = container.Resolve<ICar>();
    
    Console.WriteLine(object.ReferenceEquals(car, car1));
    
    <register type="UnityTest.ICar,UnityTest" mapTo="UnityTest.BMW,UnityTest">
    	<lifetime type="singleton" />
    </register>
    

    线程单例(PerThreadLifetimeManager)

    同一个线程只有一个实例,不同线程就是不同实例。

    应用场景:多线程处理事务,一个线程里面只有一个ORM,只有一个Context

    container.RegisterType<ICar, Ford>(new PerThreadLifetimeManager());
    
    ICar car1 = null;
    ICar car2 = null;
    ICar car3 = null;
    
    Action act1 = new Action(()=> 
    {
        car1 = container.Resolve<ICar>();
        Console.WriteLine($"car1线程id={Thread.CurrentThread.ManagedThreadId}");
    });
    var result1 = act1.BeginInvoke(null,null);
    
    
    Action act2 = new Action(()=> 
    {
        car2 = container.Resolve<ICar>();
        Console.WriteLine($"car2线程id={Thread.CurrentThread.ManagedThreadId}");
    });
    var result2 = act2.BeginInvoke(t=> 
    {
        car3 = container.Resolve<ICar>();
        Console.WriteLine($"car3线程id={Thread.CurrentThread.ManagedThreadId}");
        Console.WriteLine($"object.ReferenceEquals(car1, car2):{object.ReferenceEquals(car2, car3)}");
    },null);
    
    act1.EndInvoke(result1);
    act2.EndInvoke(result2);
    
    Console.WriteLine($"object.ReferenceEquals(car1, car2):{object.ReferenceEquals(car1, car2)}");
    

    其他生命周期

    1. HierarchicalLifetimeManager分级容器单例,子容器的概念。

    分层生命周期管理器,类似ContainerControlledLifetimeManager,是由UnityContainer管理,也是单例实例。与ContainerControlledLifetimeManager不同的是,这个生命周期管理器是分层的,因为Unity容器是可以嵌套的,所以这个生命周期管理器就是针对这种情况,当使用了这种生命周期管理器,父容器 和子容器所维护的对象生命周期是由各自的容器来管理。

    1. ExternallyControlledLifetimeManager,外部可释放单例

    2. PerResolveLifetimeManager,循环引用,不提倡使用,这种循环引用要尽量避免

    登峰造极的成就源于自律
  • 相关阅读:
    给伪类设置z-index= -1;
    UITextView的字数限制 及 添加自定义PlaceHolder
    UIView 翻转动画
    viewController的自动扩展属性导致TableViewGroupStyle时向上填充
    指针属性直接赋值 最好先retain 否则内存释放导致crash
    UIButton 点击后变灰
    IOS 设置透明度导致底层View始终可见
    UIDatePicker 时间选择器
    放大Button热区的方法哟
    数组套字典排序
  • 原文地址:https://www.cnblogs.com/fishpond816/p/14494834.html
Copyright © 2020-2023  润新知