Castle windsor添加条件依赖

Mar*_*ark 8 c# conditional castle-windsor castle

我有2个相同接口的实现,如果用户登录则要使用implementation1,如果用户没有登录则要使用implementation2.如何使用castle windsor进行配置?

moo*_*000 8

您可以添加一个处理程序选择器,它可以在可用的实现之间进行选择,具体取决于例如是否Thread.CurrentPrincipal已设置(或者HttpContext.Current.Request.IsAuthenticated如果我没记错,则在ASP.NET/MVC中).

处理程序选择器可能看起来像这样:

public class MyAuthHandlerSelector : IHandlerSelector
{
    public bool HasOpinionAbout(string key, Type service)
    {
        return service == typeof(ITheServiceICareAbout);
    }

    public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
    {
        return IsAuthenticated 
            ? FindHandlerForAuthenticatedUser(handlers)
            : FindGuestHandler(handlers);
    }

    bool IsAuthenticated
    {
        get { return Thread.CurrentPrincipal != null; } 
    }
    // ....
}
Run Code Online (Sandbox Code Playgroud)

处理程序选择器的唯一缺点是它们不是从容器中拉出来的 - 即它们在注册时作为实例添加到容器中,因此它们不会注入依赖项,管理生活方式等,但是是减轻这种情况的方法 - 如果你有兴趣了解如何做到这一点,请看看FTWindsor.


Shu*_*med 1

解决此问题的一种方法是,使用密钥注册服务,然后根据需要进行解决。

public interface ISample
{
    int Calculate(int a, int b);
}

class SampleB : ISample
{
    public int Calculate(int a, int b)
    {
        return a + b + 10;
    }
}

class SampleA : ISample
{
    public int Calculate(int a, int b)
    {
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

注册:

        container.Register(Component.For<ISample>().ImplementedBy<SampleA>().Named("SampleA").LifeStyle.Transient);
        container.Register(Component.For<ISample>().ImplementedBy<SampleB>().Named("SampleB").LifeStyle.Transient);
Run Code Online (Sandbox Code Playgroud)

// 当需要 SampleA 时解决。

var sampleA = container.Resolve<ISample>("SampleA");
Run Code Online (Sandbox Code Playgroud)

// 当需要 SampleB 时解决。

var sampleB = container.Resolve<ISample>("SampleB");
Run Code Online (Sandbox Code Playgroud)