Castle,在装饰器和装饰组件之间共享一个瞬态组件

时间:2010-05-28 08:11:01

标签: castle-windsor ioc-container

考虑以下示例:

public interface ITask
{
    void Execute();
}

public class LoggingTaskRunner : ITask
{
    private readonly ITask _taskToDecorate;
    private readonly MessageBuffer _messageBuffer;

    public LoggingTaskRunner(ITask taskToDecorate, MessageBuffer messageBuffer)
    {
        _taskToDecorate = taskToDecorate;
        _messageBuffer = messageBuffer;
    }

    public void Execute()
    {
        _taskToDecorate.Execute();
        Log(_messageBuffer);
    }

    private void Log(MessageBuffer messageBuffer)
    {}
}

public class TaskRunner : ITask
{
    public TaskRunner(MessageBuffer messageBuffer)
    {

    }

    public void Execute()
    {
    }
}

public class MessageBuffer
{

}


public class Configuration
{
    public void Configure()
    {
        IWindsorContainer container = null;

        container.Register(
            Component.For<MessageBuffer>()
                .LifeStyle.Transient);

        container.Register(
            Component.For<ITask>()
                .ImplementedBy<LoggingTaskRunner>()
                .ServiceOverrides(ServiceOverride.ForKey("taskToDecorate").Eq("task.to.decorate")));

        container.Register(
            Component.For<ITask>()
            .ImplementedBy<TaskRunner>()
            .Named("task.to.decorate"));

    }

}

如何让Windsor实例化“共享”瞬态组件,以便“装饰器”和“装饰”都获得相同的实例?

编辑:由于设计正在被批评,我发布的内容更贴近应用程序中的内容。也许有人可以建议一个更好的解决方案(如果在记录器和真正的任务之间共享瞬态资源被认为是一个糟糕的设计)

Edit2:Castle3通过引入“绑定”生活方式增加了对此(http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx)的支持

1 个答案:

答案 0 :(得分:1)

'瞬态'明确意味着'非共享',所以你所要求的在概念上是错误的。 正确解决方案是将Shared注册为Singleton而不是Transient:

container.Register(Component.For<Shared>());

(Singleton是Windsor的默认生命周期。)

然而,我怀疑所述问题的背后是一个更为复杂的问题。我猜你需要Shared才能成为瞬态,因为在很多其他情况下你需要这种生活方式,但正是在谈到Decorator和装饰之间的关系时你需要分享它们。

我仍然认为这听起来像是一种设计嗅觉,但至少有两种方法可以达到这个效果。

第一个选项涉及过早解析Shared并明确地将已解析的实例提供给两个IFoo注册的配置:

container.Register(Component.For<Shared>().LifeStyle.Transient);

var r = container.Resolve<Shared>();

container.Register(Component
    .For<IFoo>()
    .ImplementedBy<Decorator>()
    .DependsOn(new { resource = r }));
container.Register(Component
    .For<IFoo>()
    .ImplementedBy<Decorated>()
    .DependsOn(new { resource = r }));

第二个选项是为Shared进行专门的命名注册,该注册仅由IFoo注册使用:

container.Register(Component.For<Shared>().LifeStyle.Transient);
container.Register(Component.For<Shared>().Named("shared"));
container.Register(Component
    .For<IFoo>()
    .ImplementedBy<Decorator>()
    .ServiceOverrides(new { resource = "shared" }));
container.Register(Component
    .For<IFoo>()
    .ImplementedBy<Decorated>()
    .ServiceOverrides(new { resource = "shared" }));