代码改变世界

Unity 学习笔记(3) -- 生命周期管理

2009-04-28 23:34  Timothy Ye  阅读(719)  评论(0编辑  收藏  举报

Unity根据我们在注册类型的时候所指定的生命周期来管理注册类型的创建和解析。当我们在向容器中注册类型的时候,如果我们没有显式的指明该类型的生命周期管理器(下称:Lifetime Manager),默认的情况下,容器会为我们注册的类型创建一个生命周期短暂的管理器。这样一来,当我们每次调用容器的Resolve方法或者ResolveAll方法,或者采用依赖机制注入实例到其他的类中的时候,容器都会为我们创建新的实例,并且容器不会保存对实例的引用。

容器的RegisterType函数包含多个支持泛型的重载,同时还包含了一一对应的非泛型重载。其中的重载函数,我们可以看到类似下面的声明:

 1: RegisterType<TFrom, TTo>(LifetimeManager lifetime)

参数中的LifetimeManager类型,就是用来控制注册类型生命周期的。Unity中提供了几个继承自LifetimeManager的类作为注册类型的生命周期管理器。在目前的Unity 1.2版本中,共提供了3个LifetimeManager供我们直接在代码中调用。此外,我们也可以实现自己的LifetimeManager,不过必须实现LifetimeManager所必须的一些方法。

1.ContainerControlledLifetimeManager:

   容器负责管理注册类型的生命周期,并且注册类型的生命周期和容器一致。当离开容器的作用域范围时,容器会被销毁,同时其中的注册类型也会被销毁。或者,当容器被显式销毁时,其中的注册类型也同样被销毁。但是在容器有效的作用域范围中,当我们使用Resolve方法,或者使用ResolveAll方法获取我们的注册类型的时候,容器会在第一次调用时,创建实例,但是在后面的调用中,我们始终只会得到相同的实例。我们可以利用这种Manager来实现Singleton模式。

2.ExternallyControlledLifetimeManager:

和上一种方式类似,不过容器在不会保留对注册类型的强引用,而只是保留弱引用。也就是说,如果这个注册类型没有在其他地方被强引用的时候,那么这个注册类型可能会被GC给干掉。

3.PerThreadLifetimeManager:

容器保证在每个线程中返回同一个对象实例,那么在不同的线程中,得到的实例是不同的。

 

下面我们可以试验一下不同的LifetimeManager的效果

 

a. 默认的情况,不显示的指明LifetimeManager

代码:

 1: namespace UnityDemo
 2: {
 3:  class Program
 4:  {
 5:  static void Main(string[] args)
 6:  {
 7:  IUnityContainer container = new UnityContainer();
 8:  container.RegisterType<INotify, EmailNotify>();
 9:  
 10:  INotify notify1 = container.Resolve<INotify>();
 11:  
 12:  INotify notify2 = container.Resolve<INotify>();
 13:  
 14:  Console.WriteLine("notify1:" + notify1.GetHashCode());
 15:  Console.WriteLine("notify2:" + notify2.GetHashCode());
 16:  
 17:  Console.ReadLine();
 18:  }
 19:  }
 20: }

运行结果:

4

从结果我们可以看到,默认情况下不指定LifetimeManager的时候,每次我们获得的Instance其实不是同一个Instance.

 

b.使用ContainerControlledLifetimeManager

代码:

 1: namespace UnityDemo
 2: {
 3:  class Program
 4:  {
 5:  static void Main(string[] args)
 6:  {
 7:  IUnityContainer container = new UnityContainer();
 8:  container.RegisterType<INotify, EmailNotify>(new ContainerControlledLifetimeManager());
 9:  
 10:  INotify notify1 = container.Resolve<INotify>();
 11:  
 12:  INotify notify2 = container.Resolve<INotify>();
 13:  
 14:  Console.WriteLine("notify1:" + notify1.GetHashCode());
 15:  Console.WriteLine("notify2:" + notify2.GetHashCode());
 16:  
 17:  Console.ReadLine();
 18:  }
 19:  }
 20: }

运行结果:

5
使用ContainerControlledLifetimeManager,在Container生命中期内,我们得到的Instance是同一个。

 

c.使用PerThreadLifetimeManager

代码:

 1: namespace UnityDemo
 2: {
 3:  class Program
 4:  {
 5:  static void Main(string[] args)
 6:  {
 7:  IUnityContainer container = new UnityContainer();
 8:  container.RegisterType<INotify, EmailNotify>(new PerThreadLifetimeManager());
 9:  
 10:  Thread thread1 = new Thread(new ParameterizedThreadStart(ThreadProc1));
 11:  Thread thread2 = new Thread(new ParameterizedThreadStart(ThreadProc2));
 12:  
 13:  thread1.Start(container);
 14:  thread2.Start(container);
 15:  
 16:  Console.ReadLine();
 17:  }
 18:  
 19:  static void ThreadProc1(object obj)
 20:  {
 21:  INotify notify1 = (obj as IUnityContainer).Resolve<INotify>();
 22:  INotify notify2 = (obj as IUnityContainer).Resolve<INotify>();
 23:  
 24:  Console.WriteLine("ThreadProc1 --- notify1:" + notify1.GetHashCode());
 25:  Console.WriteLine("ThreadProc1 --- notify2:" + notify2.GetHashCode());
 26:  
 27:  }
 28:  
 29:  static void ThreadProc2(object obj)
 30:  {
 31:  INotify notify1 = (obj as IUnityContainer).Resolve<INotify>();
 32:  INotify notify2 = (obj as IUnityContainer).Resolve<INotify>();
 33:  
 34:  Console.WriteLine("ThreadProc2 --- notify1:" + notify1.GetHashCode());
 35:  Console.WriteLine("ThreadProc2 --- notify2:" + notify2.GetHashCode());
 36:  }
 37:  }
 38: }
运行结果:
6
 
 在结果中可以看到,同一个线程中连续两次获取到的是同一个Instance,而不同的线程中获取到的Instance不一样。