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