一. Unity声明周期

   Unity容器为我们提供了6种生命周期,便于我们根据项目需求来选择使用。

  (1). 瞬时。默认省略即为瞬时,无论单线程还是多线程,每次都重新创建对象。new TransientLifetimeManager()

  (2). 容器单例。只要是同一个Unity容器创建的同一个类型的对象,无论是线程之间还是单线程内都是单例的。new ContainerControlledLifetimeManager()

  (3). 线程单例。同一个线程内创建的同一个类型的对象,都是单例的。但线程之间不是单例的。new PerThreadLifetimeManager()

  (4). 分级容器单例。unity容器可以创建很多子容器,每个子容器无论怎么创建对象,都是单例的,但是子容器之间不是单例的。new HierarchicalLifetimeManager()

  (5). 外部可释放单例。在不销毁的情况下,每次Resolve都会返回同一个对象,即是单例的;销毁后,重新创建一个新的对象,销毁后创建的新对象又是单例的。new ExternallyControlledLifetimeManager()

  (6).循环引用。new PerResolveLifetimeManager(),不推荐使用,暂不测试。

  下面同样先通过代码的形式来测试以上几种情况。

 (1). 瞬时

 1  {
 2                 Console.WriteLine("-------------------  05-Unity的生命周期-瞬时(1)  -------------------");
 3                 IUnityContainer container = new UnityContainer();
 4                 container.RegisterType<IPhone, AndroidPhone>(new TransientLifetimeManager());   //默认省略就是瞬时的
 5 
 6                 //下面测试多线程中创建的对象是否是单例的(iphone1是一个线程  iphone2和iphone3是同一个线程)
 7                 IPhone iphone1 = null;
 8                 Action act1 = () =>
 9                 {
10                     iphone1 = container.Resolve<IPhone>();
11                     Console.WriteLine("iphone1由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
12                 };
13                 var result1 = act1.BeginInvoke(null, null);
14                 IPhone iphone2 = null;
15                 Action act2 = () =>
16                 {
17                     iphone2 = container.Resolve<IPhone>();
18                     Console.WriteLine("iphone2由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
19                 };
20                 //在act2的异步回调中创建iphone3(iphone2和iphone3是一个线程创建的)
21                 IPhone iphone3 = null;
22                 var result2 = act2.BeginInvoke(t =>
23                 {
24                     iphone3 = container.Resolve<IPhone>();
25                     Console.WriteLine("iphone3由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
26                     //代表两个不同线程创建的对象
27                     Console.WriteLine("iphone1和iphone2是否相等?{0}", object.ReferenceEquals(iphone1, iphone2));
28                     //代表同一个线程创建的两个对象
29                     Console.WriteLine("iphone2和iphone3是否相等?{0}", object.ReferenceEquals(iphone2, iphone3));
30                 }, null);
31 
32                 //线程等待
33                 act1.EndInvoke(result1);
34                 act2.EndInvoke(result2);
35 
36                 //总结:瞬时创建无论单个线程内还是多个线程之间,都不是单例的,每次调用都要重新创建对象
37 
38             }

02-Unity深入浅出(二)

  分析:iphone2和iphone3是同一个线程创建的,iphone1是单独一个线程创建的。经过结果分析:iphone1和iphone2不相等,iphone2和iphone3不相等,证明:瞬时容器无论是线程内,还是线程与线程之间每次都是重新创建的,都不是单例。

 (2). 容器单例

 1   {
 2                 Console.WriteLine("-------------------  05-Unity的生命周期-容器单例(2)  -------------------");
 3                 IUnityContainer container = new UnityContainer();
 4                 container.RegisterType<IPhone, AndroidPhone>(new ContainerControlledLifetimeManager());
 5 
 6                 //下面测试多线程中创建的对象是否是单例的(iphone1是一个线程  iphone2和iphone3是同一个线程)
 7                 IPhone iphone1 = null;
 8                 Action act1 = () =>
 9                 {
10                     iphone1 = container.Resolve<IPhone>();
11                     Console.WriteLine("iphone1由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
12                 };
13                 var result1 = act1.BeginInvoke(null, null);
14                 IPhone iphone2 = null;
15                 Action act2 = () =>
16                 {
17                     iphone2 = container.Resolve<IPhone>();
18                     Console.WriteLine("iphone2由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
19                 };
20                 //在act2的异步回调中创建iphone3(iphone2和iphone3是一个线程创建的)
21                 IPhone iphone3 = null;
22                 var result2 = act2.BeginInvoke(t =>
23                 {
24                     iphone3 = container.Resolve<IPhone>();
25                     Console.WriteLine("iphone3由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
26                     //代表两个不同线程创建的对象
27                     Console.WriteLine("iphone1和iphone2是否相等?{0}", object.ReferenceEquals(iphone1, iphone2));
28                     //代表同一个线程创建的两个对象
29                     Console.WriteLine("iphone2和iphone3是否相等?{0}", object.ReferenceEquals(iphone2, iphone3));
30                 }, null);
31 
32                 //线程等待
33                 act1.EndInvoke(result1);
34                 act2.EndInvoke(result2);
35 
36                 //总结:容器单例:只要是同一个Unity容器创建的一个类,无论是线程之间还是单线程内都是单例的
37             }

02-Unity深入浅出(二)

  分析:iphone2和iphone3是同一个线程创建的,iphone1是单独一个线程创建的。经过结果分析:iphone1和iphone2相等,iphone2和iphone3相等,证明:容器单例无论是线程内,还是线程与线程之间都是单例的。

 (3). 线程单例

 1  {
 2                 Console.WriteLine("-------------------  05-Unity的生命周期-线程单例(3)  -------------------");
 3                 IUnityContainer container = new UnityContainer();
 4                 container.RegisterType<IPhone, AndroidPhone>(new PerThreadLifetimeManager());
 5 
 6                 //下面测试多线程中创建的对象是否是单例的(iphone1是一个线程  iphone2和iphone3是同一个线程)
 7                 IPhone iphone1 = null;
 8                 Action act1 = () =>
 9                 {
10                     iphone1 = container.Resolve<IPhone>();
11                     Console.WriteLine("iphone1由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
12                 };
13                 var result1 = act1.BeginInvoke(null, null);
14                 IPhone iphone2 = null;
15                 Action act2 = () =>
16                 {
17                     iphone2 = container.Resolve<IPhone>();
18                     Console.WriteLine("iphone2由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
19                 };
20                 //在act2的异步回调中创建iphone3(iphone2和iphone3是一个线程创建的)
21                 IPhone iphone3 = null;
22                 var result2 = act2.BeginInvoke(t =>
23                 {
24                     iphone3 = container.Resolve<IPhone>();
25                     Console.WriteLine("iphone3由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
26                         //代表两个不同线程创建的对象
27                         Console.WriteLine("iphone1和iphone2是否相等?{0}", object.ReferenceEquals(iphone1, iphone2));
28                         //代表同一个线程创建的两个对象
29                         Console.WriteLine("iphone2和iphone3是否相等?{0}", object.ReferenceEquals(iphone2, iphone3));
30                 }, null);
31 
32                 //线程等待
33                 act1.EndInvoke(result1);
34                 act2.EndInvoke(result2);
35 
36                 /*
37                  * 总结:线程单例:同一个线程内,eg:iphone2和iphone3,都是AndroidPhone类型,他是单例的,不重复创建,但是线程与线程之间创建的对象就不是单例的了。
38                  * 与框架中EF上下文 利用CallContext保存的原理一致
39                  一般来说不建议在使用RegisterInstance对已存在的对象注册关系时使用PerThreadLifetimeManager,因为此时的对象已经在一个线程内创建了,如果再使用这个生命周期管理器,将无法保证其正确调用
40                  */
41             }

02-Unity深入浅出(二)

  分析:iphone2和iphone3是同一个线程创建的,iphone1是单独一个线程创建的。经过结果分析:iphone1和iphone2不相等,iphone2和iphone3相等,证明:线程单例在线程内是单例的,但线程与线程之间不是单例的。

 (4). 分级容器单例

 1  {
 2                 Console.WriteLine("-------------------  05-Unity的生命周期-分级容器单例(4)  -------------------");
 3                 //父Unity容器
 4                 IUnityContainer container = new UnityContainer();
 5                 container.RegisterType<IPhone, AndroidPhone>(new HierarchicalLifetimeManager());
 6                 //子Unity容器1
 7                 IUnityContainer childContainer1 = container.CreateChildContainer();
 8                 childContainer1.RegisterType<IPhone, AndroidPhone>(new HierarchicalLifetimeManager());
 9                 //子Unity容器2
10                 IUnityContainer childContainer2 = container.CreateChildContainer();
11                 childContainer2.RegisterType<IPhone, AndroidPhone>(new HierarchicalLifetimeManager());
12 
13                 IPhone iphone1 = container.Resolve<IPhone>();
14                 IPhone iphone2 = container.Resolve<IPhone>();
15                 IPhone iphone3 = childContainer1.Resolve<IPhone>();
16                 IPhone iphone4 = childContainer1.Resolve<IPhone>();
17                 IPhone iphone5 = childContainer2.Resolve<IPhone>();
18                 IPhone iphone6 = childContainer2.Resolve<IPhone>();
19 
20                 Console.WriteLine("父容器container第一次创建的对象的hashCode值:{0}", iphone1.GetHashCode());
21                 Console.WriteLine("父容器container第二次创建的对象的hashCode值:{0}", iphone2.GetHashCode());
22 
23                 Console.WriteLine("子容器childContainer1第一次创建的对象的hashCode值:{0}", iphone3.GetHashCode());
24                 Console.WriteLine("子容器childContainer1第二次创建的对象的hashCode值:{0}", iphone4.GetHashCode());
25 
26                 Console.WriteLine("子容器childContainer2第一次创建的对象的hashCode值:{0}", iphone5.GetHashCode());
27                 Console.WriteLine("子容器childContainer2第二次创建的对象的hashCode值:{0}", iphone6.GetHashCode());
28 
29                 //总结:unity容器可以创建很多子容器,每个子容器无论怎么创建对象,都是单例的,但是子容器之间不是单例的。
30                 //好处:我们可以对于不同生命周期的对象放在不同容器中,如果一个子容器释放,不会影响其它子容器的对象,
31                 //但是如果根节点处的父容器被释放,所有的子容器都将被释放
32             }

02-Unity深入浅出(二)

  分析:每个子容器创建的对象的值是相同的,子容器之间创建的对象是不同的

 (5). 外部可释放单例

 1   {
 2                 Console.WriteLine("------------------- 05-Unity的生命周期-外部可释放单例(5)  -------------------");
 3                 IUnityContainer container = new UnityContainer();
 4                 container.RegisterType<IPhone, AndroidPhone>(new ExternallyControlledLifetimeManager());
 5 
 6                 IPhone iphone1 = container.Resolve<IPhone>();
 7                 IPhone iphone2 = container.Resolve<IPhone>();
 8                 Console.WriteLine("第一次调用:{0}", iphone1.GetHashCode());
 9                 Console.WriteLine("第二次调用:{0}", iphone2.GetHashCode());
10 
11                 Console.WriteLine("------------------ GC回收过后  ------------------------");
12                 iphone1 = iphone2 = null;
13                 GC.Collect();
14                 Console.WriteLine("回收后第一次调用:{0}", container.Resolve<IPhone>().GetHashCode());
15                 Console.WriteLine("回收后第二次调用:{0}", container.Resolve<IPhone>().GetHashCode());
16 
17                 //总结:在不销毁的情况下,每次Resolve都会返回同一个对象,即是单例的;销毁后,重新创建一个新的对象
18                 //销毁后创建的新对象又是单例的。
19 
20 
21             }

02-Unity深入浅出(二)

  分析:回收前创建的对象都是单例的,回收后重新创建的对象还是单例的。

 (6). 循环引用

   不推荐使用。

 

二. 配置文件的形式实现

  Unity在实际开发环境中, 注册类型(包括注入对象、声明生命周期)的那一步,都是在配置文件中声明的,这才是Unity的真谛所在,才能实现真正意义上的解耦,只需将Service层的DLL文件复制到主程序bin文件夹中即可,不需要直接添加对Service层的引用。

  该实现形式主要分为以下几步:

  (1). 编写配置文件的内容。(需要将该配置文件的属性改为“始终复制”,使其可以生成到主程序的bin文件中)。

      (2). 固定4行代码读取配置文件。

1   ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
2                     fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径
3                     Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
4                     UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
View Code

相关文章: