Как Windsor может создать один компонент для каждого вызова разрешения? - PullRequest
0 голосов
/ 08 июля 2010

Рассмотрим следующие классы:

public interface IView
{
    /// <summary>
    /// Ignore this (its only for the assertion)
    /// </summary>
    ITask Task { get; }
}

public class ViewA : IView
{
    private readonly ITask _task;

    public ViewA(ITask task)
    {
        _task = task;
    }

    public ITask Task
    {
        get { return _task; }
    }
}
public class ViewB : IView
{
    private readonly ITask _task;

    public ViewB(ITask task)
    {
        _task = task;
    }

    public ITask Task
    {
        get { return _task; }
    }
}

public class ViewManager
{
    private readonly List<IView> _views;

    public ViewManager(IView[] views)
    {
        _views = new List<IView>(views);
    }

    public ReadOnlyCollection<IView> Views
    {
        get { return new ReadOnlyCollection<IView>(_views); }
    }
}

И, наконец, то, что я пытаюсь достичь:

    [Fact]
    public void Configure_TwoServicesWithDependencyToTransientComponent_BothShareComponent()
    {
        // arrange
        var windsorContainer = new WindsorContainer();

        windsorContainer.Kernel.Resolver.AddSubResolver(new ArrayResolver(windsorContainer.Kernel));

        windsorContainer.Register(Component.For<ITask>()
            .ImplementedBy<TaskWithNoDependencies>()
            .Named("task")
            .LifeStyle.Transient);

        windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewA>().LifeStyle.Transient);
        windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewB>().LifeStyle.Transient);

        windsorContainer.Register(Component.For<ViewManager>()
            .LifeStyle.Transient);

        // act
        ViewManager service = windsorContainer.Resolve<ViewManager>();

        // assert
        Assert.Same(service.Views[0].Task, service.Views[1].Task);
    }

Как я могу заставить Виндзор создать экземпляр ITask, чтобы он был общим дляViewA и ViewB при разрешении ViewManager?Я попробовал следующее, но это не сработало:

        windsorContainer.Register(Component.For<ViewManager>()
            .DynamicParameters((k, d) =>
                                   {
                                       d["task"] = k.Resolve<ITask>();

                                   })
            .LifeStyle.Transient);

Ответы [ 2 ]

0 голосов
/ 09 июля 2010

Я нашел решение, но я надеюсь, что кто-то может предложить лучшее. Пожалуйста, дайте мне немного критики по выбранному решению:

    [Fact]
    public void Configure_TwoServicesWithDependencyToTransientComponent_BothShareComponent()
    {
        // arrange
        var windsorContainer = new WindsorContainer();

        windsorContainer.Kernel.Resolver.AddSubResolver(new ArrayResolver(windsorContainer.Kernel));

        windsorContainer.Register(Component.For<ITask>().ImplementedBy<TaskWithNoDependencies>().LifeStyle.Custom(typeof(PerScopeOrTransientLifestyleManager)));

        windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewA>().LifeStyle.Transient);
        windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewB>().LifeStyle.Transient);

        windsorContainer.Register(Component.For<ViewManager>()
            .LifeStyle.Transient);

        // act
        ViewManager service;

        using (new LifeStyleScope())
        {
            service = windsorContainer.Resolve<ViewManager>();
        }

        // assert
        Assert.Same(service.Views[0].Task, service.Views[1].Task);
    }

Я сделал две вещи:

  1. Создан собственный менеджер образа жизни, в который добавлена ​​возможность говорить, что компоненты будут действовать как переходные за пределами области образа жизни и как синглтон внутри одного.

  2. Создана область образа жизни, которую я могу использовать для указания "контекста-границы".

Есть одна вещь, которая мне не нравится в этом решении, это тот факт, что вы должны знать о проблеме контекста с сайта call-сайта. Я мог бы абстрагировать это, переместив область образа жизни в viewmanager, но тогда viewmanager должен иметь зависимость ioc, что потребует некоторой дополнительной заглушки при тестировании viewmanager.

0 голосов
/ 08 июля 2010
  1. Почему вы хотите сделать это так? То, что вы пытаетесь сделать, это связать экземпляр с контекстом дерева зависимостей. Возможно, контекст шире, как веб-запрос? Какова причина, почему вы хотите сделать это так.

  2. Возможно, но я знаю чистый способ сделать это с помощью Windsor 2.5. Предыдущая версия, вероятно, требует некоторой хитрости.

...