我有一个课程,呼吁互联网服务获取一些数据:
public class MarketingService { private IDataProvider _provider; public MarketingService(IDataProvider provider) { _provider = provider; } public string GetData(int id) { return _provider.Get(id); } }
目前我有两个提供程序:HttpDataProvider和FileDataProvider.通常我会连接到HttpDataProvider,但如果外部Web服务失败,我想更改系统以绑定到FileDataProvider.就像是:
public string GetData(int id) { string result = ""; try { result = GetData(id); // call to HttpDataProvider } catch (Exception) { // change the Windsor binding so that all future calls go automatically to the // FileDataProvier // And while I'm at it,retry against the FileDataProvider } return result; }
因此,当执行此操作时,所有将来的MarketingService实例都将自动连接到FileDataProvider.有人知道如何动态改变Windsor绑定吗?
解决方法
一种解决方案是使用选择器
public class ForcedImplementationSelector<TService> : IHandlerSelector { private static Dictionary<Type,Type> _forcedImplementation = new Dictionary<Type,Type>(); public static void ForceTo<T>() where T: TService { _forcedImplementation[typeof(TService)] = typeof(T); } public static void ClearForce() { _forcedImplementation[typeof(TService)] = null; } public bool HasOpinionAbout(string key,Type service) { return service == typeof (TService); } public IHandler SelectHandler(string key,Type service,IHandler[] handlers) { var tService = typeof(TService); if (_forcedImplementation.ContainsKey(tService) && _forcedImplementation[tService] != null) { return handlers.FirstOrDefault(handler => handler.ComponentModel.Implementation == _forcedImplementation[tService]); } // return default return handlers[0]; } }
测试和使用
[TestFixture] public class Test { [Test] public void ForceImplementation() { var container = new WindsorContainer(); container.Register(Component.For<IFoo>().ImplementedBy<Foo>()); container.Register(Component.For<IFoo>().ImplementedBy<Bar>()); container.Kernel.AddHandlerSelector(new ForcedImplementationSelector<IFoo>()); var i = container.Resolve<IFoo>(); Assert.AreEqual(typeof(Foo),i.GetType()); ForcedImplementationSelector<IFoo>.ForceTo<Bar>(); i = container.Resolve<IFoo>(); Assert.AreEqual(typeof(Bar),i.GetType()); ForcedImplementationSelector<IFoo>.ClearForce(); i = container.Resolve<IFoo>(); Assert.AreEqual(typeof(Foo),i.GetType()); } }