黃偉榮的學習筆記

軟體的世界變化萬千,小小的我只能在這洪流奮發向上以求立足。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

IoC的中繼器:CommonServiceLocator

Posted on 2011-01-30 02:38  黃偉榮  阅读(2245)  评论(0编辑  收藏  举报

IoC(控制反轉)是時下很流行的設計模式,它可以大大的簡少程式之間的相依性,有點像工廠模式,在Class中操作的都是Interface,而Interface與Class的對應與建立實例都是由IoC Framework處理,光是在.Net Framework下的IoC Framework就有近10套,每套都有各自的優缺點,呼叫方式也略有不同,切換IoC Framework是非常麻煩的,或是開發組件(Assembly),組件也是使用IoC,但是又不能限制使用端用特定款IoC Framework,這時候可以考慮使用IoC的中繼器:CommonServiceLocator來解決這個問題。

NOTE:

IoC的文章很多人寫,而且也寫的非常完整與詳細,小弟就不在這裡多述,各位可以參考以下文章:

In 91 : [Software Architecture]IoC and DI

黃忠成 :  Inside ObjectBuilder Part1

 

什麼是CommonServiceLocator

service locator 2

官方網址:http://commonservicelocator.codeplex.com/

CommonServiceLocator是放在Codeplex中由Microsoft patterns & practices團隊所設計的小組件,它很輕所有的Code才一百多行,它主要的定義一些Interface,讓我們的程式是呼叫CommonServiceLocator,透過CommonServiceLocator去呼叫IoC Framework,如同中繼器一般,使我們的程式不會綁死於一同IoC Framework,而且有提供主流的IoC Framework用的Provider(就算未提供也可以自己寫),支援非常的廣泛。

支援的IoC Framework如下:

  • Castle Windsor
  • Spring .NET
  • Unity
  • StructureMap
  • Autofac
  • MEF
  • LinFu

 

使用方式:

//泛型
//第一個Method,也是最常用的Method
ICreditCardService instance = ServiceLocator.Current.GetInstance<ICreditCardService>();

//第二個多載Method,因為一個Interface,所能有很多個Class實作,如果有設定Key,可以用Key指定要實例的Type
ICreditCardService instance = ServiceLocator.Current.GetInstance<ICreditCardService>("中國信託");


//非泛型的
ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetInstance(typeof(ICreditCardService));

ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetInstance(typeof(ICreditCardService), "中國信託");


//從System.IServiceProvider繼承來的,不過看了幾個Provider,GetService都只是呼叫GetInstance,所以沒什麼不同
ICreditCardService instance = (ICreditCardService)ServiceLocator.Current.GetService(typeof(ICreditCardService));

註冊Provider

//先註冊IoC的東西
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<OrderService>().As<IOrderService>();
builder.RegisterType<中國信託CreditCardService>().Named<ICreditCardService>("中國信託");
builder.RegisterType<台北富邦CreditCardService>().Named<ICreditCardService>("台北富邦");

//最後在設定Provider
ServiceLocator.SetLocatorProvider(() => new MyServiceLocator(builder)); 

 

這裡介紹幾個常見的IoC設定方式,詳情請看官方網站的說明。

Autofac的設定

Autofac網站下載AutofacContrib,加入參考AutofacContrib.CommonServiceLocator.dll

ContainerBuilder builder = new ContainerBuilder();
var container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));

 

Spring .NET的設定

下載:CommonServiceLocator.SpringAdapter.zip,加入參考CommonServiceLocator.SpringAdapter.dll

DefaultListableObjectFactory objectFactory = new DefaultListableObjectFactory(false);
objectFactory.RegisterSingleton(typeof(SimpleLogger).FullName, new SimpleLogger());
objectFactory.RegisterSingleton(typeof(AdvancedLogger).FullName, new AdvancedLogger());

ServiceLocator.SetLocatorProvider(() => new SpringServiceLocatorAdapter(objectFactory));

Unity的設定

下載:CommonServiceLocator.UnityAdapter.zip,加入參考Microsoft.Practices.Unity.ServiceLocatorAdapter.dll

IUnityContainer container = new UnityContainer() 
    .RegisterType<ILogger, AdvancedLogger>() 
    .RegisterType<ILogger, SimpleLogger>(typeof (SimpleLogger).FullName) 
    .RegisterType<ILogger, AdvancedLogger>(typeof (AdvancedLogger).FullName);

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container)); 
return new UnityServiceLocator(container);

StructureMap的設定

下載:CommonServiceLocator.StructureMapAdapter.zip,加入參考StructureMapAdapter.dll

Registry registry = new Registry();
registry.ForRequestedType<ILogger>().TheDefaultIsConcreteType<AdvancedLogger>();
registry.AddInstanceOf<ILogger>(new SimpleLogger()).WithName(typeof(SimpleLogger).FullName);
registry.AddInstanceOf<ILogger>(new AdvancedLogger()).WithName(typeof(AdvancedLogger).FullName);
IContainer container = new Container(registry);

ServiceLocator.SetLocatorProvider(() => new StructureMapServiceLocator(container));