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
什麼是CommonServiceLocator
官方網址: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));