一. 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             }

  分析: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             }

  分析: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             }

  分析: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             }

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

(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             }

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

(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

  (3). 声明Unity容器,并与配置文件关联。

1    IUnityContainer container = new UnityContainer();
2    section.Configure(container, "testContainer");

View Code

  (4). Unity解析对象。

(一).配置文件的书写形式

  下面整个Xml均为Untiy的配置文件,声明Unity容器有两种方式:①先定义别名,类型名称和程序集名称均写在别名中,然后在容器中与别名进行关联。 ②直接在容器中的register节点写类型名称和程序集名称。

  另外可以在register节点中添加<lifetime>节点,可以声明Unity的声明周期。

 1 <configuration>
 2   <configSections>
 3     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
 4   </configSections>
 5   <unity>
 6     <!-- unity容器支持AOP扩展  -->
 7     <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
 8
 9     <!--定义类型别名-->
10     <aliases>
11       <!--type的两个参数分别是:类型名称和DLL程序集的名称-->
12       <!--alias中的别名供container容器中使用-->
13       <add alias="IPhone" type="Ypf.Interface.IPhone,Ypf.Interface" />
14       <add alias="AndroidPhone" type="Ypf.Service.AndroidPhone, Ypf.Service" />
15       <add alias="ApplePhone" type="Ypf.Service.ApplePhone, Ypf.Service" />
16
17       <add alias="IMicrophone" type="Ypf.Interface.IMicrophone, Ypf.Interface" />
18       <add alias="IHeadphone" type="Ypf.Interface.IHeadphone, Ypf.Interface" />
19       <add alias="IPower" type="Ypf.Interface.IPower, Ypf.Interface" />
20       <add alias="Microphone" type="Ypf.Service.Microphone, Ypf.Service" />
21       <add alias="Headphone" type="Ypf.Service.Headphone, Ypf.Service" />
22       <add alias="Power" type="Ypf.Service.Power, Ypf.Service" />
23     </aliases>
24
25
26     <!-- unity容器配置注册节点-->
27     <containers>
28       <!--容器配置方式一:类型名称和程序集名称全部写在容器中-->
29       <container name="testContainer">
30         <!--  type和mapTo中的两个参数分别是:类型名称和DLL程序集的名称 -->
31         <!--  type和mapTo分别对应RegisterType<A,B> 中的A和B两个值-->
32         <register type="Ypf.Interface.IPhone,Ypf.Interface" mapTo="Ypf.Service.AndroidPhone, Ypf.Service"/>
33         <register type="Ypf.Interface.IPhone,Ypf.Interface" mapTo="Ypf.Service.AndroidPhone, Ypf.Service" name="android"/>
34         <register type="Ypf.Interface.IPhone,Ypf.Interface" mapTo="Ypf.Service.ApplePhone, Ypf.Service" name="apple"/>
35         <!--以下三个属于依赖注入的内容了-->
36         <register type="Ypf.Interface.IMicrophone, Ypf.Interface" mapTo="Ypf.Service.Microphone, Ypf.Service"/>
37         <register type="Ypf.Interface.IHeadphone, Ypf.Interface" mapTo="Ypf.Service.Headphone, Ypf.Service"/>
38         <register type="Ypf.Interface.IPower, Ypf.Interface" mapTo="Ypf.Service.Power, Ypf.Service"/>
39       </container>
40
41       <!--容器配置方式二:配合aliases类型别名进行使用-->
42       <container name="testContainer2">
43         <!--  type和mapTo中的两个参数分别是:类型名称和DLL程序集的名称 -->
44         <!--  type和mapTo分别对应RegisterType<A,B> 中的A和B两个值-->
45         <register type="IPhone" mapTo="AndroidPhone"/>
46         <register type="IPhone" mapTo="AndroidPhone" name="android"/>
47         <register type="IPhone" mapTo="ApplePhone" name="apple"/>
48         <!--以下三个属于依赖注入的内容了-->
49         <register type="IMicrophone" mapTo="Microphone"/>
50         <register type="IHeadphone" mapTo="Headphone"/>
51         <register type="IPower" mapTo="Power"/>
52       </container>
53
54       <!--在配置文件中配置Unity的生命周期 以AndroidPhone为例-->
55       <container name="testContainer3">
56         <!--  下面是用别名的形式, type和mapto分别对应上面的别名 -->
57         <!--  声明周期放到该节点里面用lifetime进行包裹,不用别名的形式道理一样,也是这种方式进行包裹-->
58         <register type="IPhone" mapTo="AndroidPhone">
59           <!--1. 瞬时的  默认即为瞬时的-->
60           <!--<lifetime type="TransientLifetimeManager" />-->
61           <!--2. 容器单例的-->
62           <!--<lifetime type="ContainerControlledLifetimeManager" />-->
63           <!--3. 线程单例-->
64           <!--<lifetime type="PerThreadLifetimeManager" />-->
65           <!--4. 分级容器单例-->
66           <lifetime type="hierarchical" />
67           <!--其它两种不做测试-->
68         </register>
69       </container>
70     </containers>
71
72   </unity>
73 </configuration>

(二). 容器配置方式一:类型名称和程序集名称全部写在容器中

 {//Console.WriteLine("---------------------------容器配置方式一:类型名称和程序集名称全部写在容器中--------------------------------------");///*(一). 该配置文件包含依赖注入、指定命名注册*/////1. 编写配置文件中的内容(需要将UnityConfig.xml的属性改为始终赋值,使其能生成到bin下)////2. 固定的4行代码读取配置文件ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);////3. Unity层次的步骤IUnityContainer container = new UnityContainer();section.Configure(container, "testContainer");IPhone iphone1 = container.Resolve<IPhone>();iphone1.Call();IPhone iphone2 = container.Resolve<IPhone>("apple");iphone2.Call();IPhone iphone3 = container.Resolve<IPhone>("android");iphone3.Call();}

(三). 容器配置方式二:配合aliases类型别名进行使用

 1  {
 2                     //Console.WriteLine("---------------------------容器配置方式二:配合aliases类型别名进行使用--------------------------------------");
 3                     ///*(一). 该配置文件包含依赖注入、指定命名注册*/
 4
 5                     //1. 编写配置文件中的内容(需要将UnityConfig.xml的属性改为始终赋值,使其能生成到bin下)
 6                     //2. 固定的4行代码读取配置文件
 7                     ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 8                     fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径
 9                     Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
10                     UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
11                     //3. Unity层次的步骤
12                     IUnityContainer container = new UnityContainer();
13                     section.Configure(container, "testContainer2");
14
15                     IPhone iphone1 = container.Resolve<IPhone>();
16                     iphone1.Call();
17                     IPhone iphone2 = container.Resolve<IPhone>("apple");
18                     iphone2.Call();
19                     IPhone iphone3 = container.Resolve<IPhone>("android");
20                     iphone3.Call();
21                 }

(四). Unity的生命周期-容器单例--配置文件的方式 (可以注释配置文件中的节点,来测试其他情况:瞬时、线程单例)

 1                     Console.WriteLine("-------------------  Unity的生命周期-容器单例--配置文件的方式  -------------------");
 2                     //1. 编写配置文件中的内容(需要将UnityConfig.xml的属性改为始终赋值,使其能生成到bin下)
 3                     //2. 固定的4行代码读取配置文件
 4                     ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 5                     fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径
 6                     Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
 7                     UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
 8                     //3. Unity层次的步骤
 9                     IUnityContainer container = new UnityContainer();
10                     section.Configure(container, "testContainer3");
11
12                     //下面测试多线程中创建的对象是否是单例的(iphone1是一个线程  iphone2和iphone3是同一个线程)
13                     IPhone iphone1 = null;
14                     Action act1 = () =>
15                     {
16                         iphone1 = container.Resolve<IPhone>();
17                         Console.WriteLine("iphone1由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
18                     };
19                     var result1 = act1.BeginInvoke(null, null);
20                     IPhone iphone2 = null;
21                     Action act2 = () =>
22                     {
23                         iphone2 = container.Resolve<IPhone>();
24                         Console.WriteLine("iphone2由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
25                     };
26                     //在act2的异步回调中创建iphone3(iphone2和iphone3是一个线程创建的)
27                     IPhone iphone3 = null;
28                     var result2 = act2.BeginInvoke(t =>
29                     {
30                         iphone3 = container.Resolve<IPhone>();
31                         Console.WriteLine("iphone3由线程id={0}创建", Thread.CurrentThread.ManagedThreadId);
32                         //代表两个不同线程创建的对象
33                         Console.WriteLine("iphone1和iphone2是否相等?{0}", object.ReferenceEquals(iphone1, iphone2));
34                         //代表同一个线程创建的两个对象
35                         Console.WriteLine("iphone2和iphone3是否相等?{0}", object.ReferenceEquals(iphone2, iphone3));
36                     }, null);
37
38                     //线程等待
39                     act1.EndInvoke(result1);
40                     act2.EndInvoke(result2);

(五). Unity的生命周期-分级容器-配置文件

 1                     Console.WriteLine("-------------------  Unity的生命周期-分级容器--配置文件的方式  -------------------");
 2                     //1. 编写配置文件中的内容(需要将UnityConfig.xml的属性改为始终赋值,使其能生成到bin下)
 3                     //2. 固定的4行代码读取配置文件
 4                     ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 5                     fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径
 6                     Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
 7                     UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
 8                     //3. Unity层次的步骤
 9                     IUnityContainer container = new UnityContainer();
10                     section.Configure(container, "testContainer3");
11
12                     //子Unity容器1
13                     IUnityContainer childContainer1 = container.CreateChildContainer();
14
15                     //子Unity容器2
16                     IUnityContainer childContainer2 = container.CreateChildContainer();
17
18                     IPhone iphone1 = container.Resolve<IPhone>();
19                     IPhone iphone2 = container.Resolve<IPhone>();
20                     IPhone iphone3 = childContainer1.Resolve<IPhone>();
21                     IPhone iphone4 = childContainer1.Resolve<IPhone>();
22                     IPhone iphone5 = childContainer2.Resolve<IPhone>();
23                     IPhone iphone6 = childContainer2.Resolve<IPhone>();
24
25                     Console.WriteLine("父容器container第一次创建的对象的hashCode值:{0}", iphone1.GetHashCode());
26                     Console.WriteLine("父容器container第二次创建的对象的hashCode值:{0}", iphone2.GetHashCode());
27
28                     Console.WriteLine("子容器childContainer1第一次创建的对象的hashCode值:{0}", iphone3.GetHashCode());
29                     Console.WriteLine("子容器childContainer1第二次创建的对象的hashCode值:{0}", iphone4.GetHashCode());
30
31                     Console.WriteLine("子容器childContainer2第一次创建的对象的hashCode值:{0}", iphone5.GetHashCode());
32                     Console.WriteLine("子容器childContainer2第二次创建的对象的hashCode值:{0}", iphone6.GetHashCode());

三. Unity实现AOP

待定

转载于:https://www.cnblogs.com/yaopengfei/p/7500113.html

02-Unity深入浅出(二)相关推荐

  1. Vista Media Center 开发之深入浅出 (二) --Vista Media Center 程序的新建及部署

    原文: http://www.cnblogs.com/wangmiao/articles/1306292.html Vista Media Center 开发之深入浅出 (二) ----- Vista ...

  2. Unity 生成二维码 融合图片

    Unity 生成二维码,并将二维码和已有背景图片融合,保存到本地,,, 1.场景的搭建 2.代码的编写(参考链接) using System.IO; using UnityEngine; using ...

  3. Unity创建二维码

    Unity创建二维码 1.引入Dll 下载Dll 密码:8djo 2.创建二维码 using UnityEngine; using ZXing; using ZXing.QrCode; using S ...

  4. Unity渲染(二):Shader着色器基础入门之渲染Image图片

    Unity渲染(二):图片渲染 通过这里,你会学习到怎么将一张图片渲染到UI的Image组件或者SpriteRenderer上,以及透明物体的渲染. 上一章:Unity渲染(一):着色器基础入门之纯色 ...

  5. 制作Unity的二维时间轴编辑器界面

    由于某种原因,阿赵我一直想做一个能显示二维时间轴波形的编辑器,类似于Unity自带的Profiler那样. 我抽空做了一下: 为了测试,我随机生成了一些数据,用于波形的显示. 可以选择其中的某一帧,然 ...

  6. unity生成二维码

    我这里用到GUI和UGUI来实现了一次,下载地址为http://zxingnet.codeplex.com/,我这里已经下载好了,引用一个zxing.unity.dll,下载网址https://pan ...

  7. World Locking Tools for Unity Sample (二)QR Space Pins

    World Locking Tools for Unity 基本配置 示例场景部分 工程资源 环境配置 打印二维码 虚拟世界 物理世界 基本配置 World Locking Tools 的 Space ...

  8. Unity(二十一) 关于Logitech罗技G29开发

    一:安装罗技PC软件 下载 - G920 Driving Force 赛车方向盘 – Logitech 支持 + 下载 安装完后需要重启电脑 二:Unity AssetStore下载sdk 下载导入U ...

  9. unity3D游戏开发三之unity编辑器二

    转:http://blog.csdn.net/kuloveyouwei/article/details/23020995 下面我们介绍下GameObject,游戏对象/物体,通过游戏对象我们可以创建游 ...

最新文章

  1. 脑机接口可以实时从脑电波中重建人脑中的图片?
  2. Exchange 2010与Exchange Online混合部署PART 5:配置边缘
  3. python编写程序-Python 编程速成(推荐)
  4. php查询mysql表里的数据_php查询mysql数据表记录实现代码
  5. 指针、数组、函数阶段小结
  6. CodeForces369C On Changing Tree
  7. 7、play中的文件上传
  8. spring的bean范围_Spring Bean范围
  9. 上一次系统的关闭是意外的_教你如何一键极速重装系统
  10. JPA零碎要点---JTA全局事物理解
  11. python语法_str_eval
  12. python json转xml_Python实现XML到JSON的转换并编写,python,xml,转化,为,Json,进行,写入
  13. 中医测试体质的软件,中医体质辨识软件五大功能
  14. python乱码怎么办_python中urllib.unquote乱码的原因与解决方法
  15. 您无法关机或重启此计算机,Win10不能关机或重启的四种解决方法
  16. uva 1449 Dominating Patterns(AC自动机基本应用)
  17. [渝粤教育] 中南大学 科学计算与MATLAB语言 参考 资料
  18. C语言期末设计不在是千篇一律的学生管理系统,新题设值教师工作量管理系统(数组)。
  19. ssm南工二手书交易平台 毕业设计-附源码172334
  20. EJB:First component in name xxx not found - Java / Java EE

热门文章

  1. Spring - Java/J2EE Application Framework 应用框架 第 17 章 使用Spring邮件抽象层发送Email
  2. 编程之美-求数组的子数组之和的最大值方法整理
  3. Matlab之switch-case语句
  4. 学习《CSS选择器Level-4》不完全版
  5. 记那一次-----环环相抱何是了?
  6. 数据运营者的福音:海量数据处理利器Greenplum
  7. 《云计算揭秘企业实施云计算的核心问题》——导读
  8. arcgis api for flex 开发入门(五)查询
  9. UTF-8和Unicode
  10. ACM入门练习与递推小结