castle-windsor – 为城堡windsor中的类型实现注册开放的通用装饰器

在试图强迫Windsor用随机数量的装饰器包装一个实现时,我偶然发现了以下内容:

我有3个装饰器和一个使用相同接口的实现.

如果您运行此代码,windsor将解析icommandhandler< stringcommand>作为实现,据我所知,这是预期的行为,因为类型化的实现无法在开放类型的装饰器中注册.

但是,如果取消注释行container.Register(Component.For< ICommandHandler< stringCommand>>().ImplementedBy< Decorator1< stringCommand>>());,将使用所有三个装饰器来解析实现,这是期望的结果(排序:).

class Program
{
    static void Main(string[] args)
    {
        var container = new WindsorContainer();

        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
        container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));

        //uncomment the line below and watch the magic happen
        //container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
        container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());

        var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
        var command = new stringCommand();
        stringCommandHandler.Handle(command);

        Console.WriteLine(command.s);
        Console.ReadKey();
    }
}

public interface ICommandHandler<T>
{
    void Handle(T t);
}

public class stringCommand
{
    public string s { get; set; }
}

public abstract class Decorator<T> : ICommandHandler<T>
{
    public abstract void Handle(T t);
};

public class Decorator1<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator1(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator1;";
        _handler.Handle(t);
    }
}

public class Decorator2<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator2(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator2;";
        _handler.Handle(t);
    }
}
public class Decorator3<T> : Decorator<T>
    where T : stringCommand
{
    private ICommandHandler<T> _handler;
    public Decorator3(ICommandHandler<T> handler)
    {
        _handler = handler;
    }

    public override void Handle(T t)
    {
        t.s += "Decorator3;";
        _handler.Handle(t);
    }
}

public class implementation : ICommandHandler<stringCommand>
{
    public void Handle(stringCommand t)
    {
        t.s += "implementation;";
    }
}

为什么会发生这种情况,这是我不了解的温莎特色吗?是否有不同的方法可以达到同样的效果? (不求助于反思)

最佳答案
当windsor尝试解析组件时,它将首先尝试解析更具体的接口.因此,当您注册Component.For时,它更愿意通过开放的泛型类型来解决这个问题.

如果多次注册相同的接口,它将使用指定的第一个接口.

因此,如果您不解开该应用程序将解决实现的行,因为这是最具体的组件.

如果你取消注释行decorator1将被解决,确实魔术开始.装饰器现在将开始寻找满足它的构造函数的第一个注册组件,在这种情况下,再次是decorator1(你注意到你的输出显示decorator1 2次?).哪个将解决下一个注册的组件等,直到实际实现.

所以我唯一能想到的就是不将decorator1注册为开放式泛型,而是注册为特定类型.

亲切的问候,
Marwijn.

转载注明原文:castle-windsor – 为城堡windsor中的类型实现注册开放的通用装饰器 - 代码日志