Замок, разделяющий переходный компонент между декоратором и декорированным компонентом - PullRequest
1 голос
/ 28 мая 2010

Рассмотрим следующий пример:

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 создать экземпляр "общего" переходного компонента, чтобы и "Decorator", и "Decorated" получали один и тот же экземпляр?

Редактировать: так как дизайн подвергается критике, я публикую кое-что ближе к тому, что делается в приложении. Может быть, кто-то может предложить лучшее решение (если разделение временного ресурса между регистратором и истинной задачей считается плохим проектом)

Edit2: Castle3 добавил поддержку для этого (http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx), введя «связанный» образ жизни

1 Ответ

1 голос
/ 28 мая 2010

«Переходный процесс» в явном виде означает «не разделенный», так что то, что вы просите, является концептуально неправильным. правильное решение состоит в том, чтобы зарегистрировать Shared в качестве синглтона вместо переходного процесса:

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

(Синглтон - время жизни по умолчанию в Виндзоре.)

Однако я подозреваю, что за поставленным вопросом скрывается гораздо более сложная проблема. Я предполагаю, что вам нужно Shared, чтобы быть временным, потому что он нужен вам в этом образе жизни для многих других случаев, но именно когда речь идет об отношениях между Decorator и Decorated, вам необходимо поделиться ими.

Я все еще думаю, что это звучит как запах дизайна, но есть как минимум два способа добиться этого результата.

Первый вариант предполагает преждевременное разрешение 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" }));
...