小木猫

 找回密码
 立即注册

扫一扫,访问微社区

搜索
热搜: 活动 交友 discuz
查看: 2249|回复: 6
打印 上一主题 下一主题

ServiceLocator and Unity – Be Careful

[复制链接]

373

主题

1055

帖子

5657

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5657
跳转到指定楼层
楼主
发表于 2015-8-23 10:06:47 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
Jeremiah.Clark 12 May 2009 3:00 PM

http://blogs.msdn.com/b/miah/arc ... ity-be-careful.aspx

Chris Tavarez has provided a handy adapter (UnityServiceLocator) for using ServiceLocator to resolve types from a Unity container.  You can then use ServiceLocator.SetLocatorProvider() to register the UnityServiceLocator as the default provider for ServiceLocator.

For this example, we will be using ServiceLocator and Unity to resolve the type IFoo to Foo using a singleton lifetime.  Then we will get two instances of IFoo and compare to ensure that they are the same object.

Here are four different approaches to configuring ServiceLocator and Unity that I have found during my searches on the web:

1:

   1: static void Main(string[] args)
   2: {            
   3:     UnityServiceLocator locator = new UnityServiceLocator(ConfigureUnityContainer());
   4:     ServiceLocator.SetLocatorProvider(() => locator);
   5:  
   6:     var a = ServiceLocator.Current.GetInstance<IFoo>();
   7:     var b = ServiceLocator.Current.GetInstance<IFoo>();
   8:  
   9:     Console.WriteLine(a.Equals(b));            
  10: }
  11:  
  12: private static IUnityContainer ConfigureUnityContainer()
  13: {
  14:     UnityContainer container = new UnityContainer();
  15:     container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
  16:     return container;
  17: }
2:

   1: static void Main(string[] args)
   2: {      
   3:     ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(ConfigureUnityContainer()));
   4:  
   5:     var a = ServiceLocator.Current.GetInstance<IFoo>();
   6:     var b = ServiceLocator.Current.GetInstance<IFoo>();
   7:  
   8:     Console.WriteLine(a.Equals(b));            
   9: }
  10:  
  11: private static IUnityContainer ConfigureUnityContainer()
  12: {
  13:     UnityContainer container = new UnityContainer();
  14:     container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
  15:     return container;
  16: }
3:

   1: static void Main(string[] args)
   2: {
   3:     UnityContainer container = new UnityContainer();
   4:     container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
   5:  
   6:     ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
   7:  
   8:     var a = ServiceLocator.Current.GetInstance<IFoo>();
   9:     var b = ServiceLocator.Current.GetInstance<IFoo>();
  10:  
  11:     Console.WriteLine(a.Equals(b));            
  12: }
4:

   1: static void Main(string[] args)
   2: {
   3:     UnityContainer container = new UnityContainer();
   4:     container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
   5:     UnityServiceLocator locator = new UnityServiceLocator(container);
   6:     
   7:     ServiceLocator.SetLocatorProvider(() => locator);
   8:  
   9:     var a = ServiceLocator.Current.GetInstance<IFoo>();
  10:     var b = ServiceLocator.Current.GetInstance<IFoo>();
  11:  
  12:     Console.WriteLine(a.Equals(b));            
  13: }


So these implementations seem to to do the same basic thing: register the UnityServiceLocator and use it to resolve types.  But…

howardpayne

Pop quiz:
Can you find the subtle differences and explain the problems that they can cause?

Explanation:
Example #1:  This implementation works as expected.  The two instances (a and b) reference the same container controlled object.

Example #2:  This one is just wrong.  The two instances are not the same object, but two distinct objects.  Since the argument for the SetLocatorProvider() method is a delegate, each call to ServiceLocator.Current executes the delegate again, creating a new Unity container for every call.  This one also has the same side effect as #3.

Example #3:  This one gives the correct behavior with respect to instances a and b, but leads to a new UnityServiceLocator object being created for each ServiceLocator.Current call.  This could lead to a lot of objects just hanging around until the GC runs and reclaims the memory.

Example #4:  Works as expected.  Essentially the same as #1 but without wrapping the container creation in a method.



The two primary conclusions that I came to during this exercise are:

Make sure that you understand the API and code that you are calling.  It may not always be black and white.  As in example #2 above, forgetting that this is a delegate can lead to the wrong behavior.
Don’t rely blindly on example code from the internet.  Some of the code that I have posted is probably error prone.  Sample code is just that: a sample.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表