c# - 以编程方式更改 CaSTLe Windsor 中的依赖项

标签 c# castle-windsor

我有一个调用互联网服务以获取一些数据的类:

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 服务失败,我想更改系统以绑定(bind)到 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;
}

因此,执行此操作后,所有 future 的 MarketingService 实例将自动连接到 FileDataProvider。如何即时更改 Windsor 绑定(bind)?

最佳答案

一种解决方案是使用选择器

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());
    }
}

关于c# - 以编程方式更改 CaSTLe Windsor 中的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16286667/

相关文章:

c# - 如何使用 Windsor 将依赖项注入(inject)自定义 RoleProvider?

c# - CaSTLe Windsor 如何运作?它是否包装了所有已注册的对象?

multithreading - 在 CaSTLe Windsor 上注册服务/组件是线程安全的吗?

c# - 使用 RSACryptoServiceProvider 进行公钥加密

c# - 通过浏览器进行 WCF Rest 服务 Windows 身份验证

c# - JSON.net(反)序列化未类型化的属性

c# - Windsor 的通用存储库生命周期配置

c# - 无法检索项目元数据。确保这是一个基于MSBuild的.NET Core项目。 (迁移)

c# - 确定类 x 是否派生自类 y 的最简单方法? (C#)

c# - CaSTLe Windsor - 获取正在解析的根组件类型