Заказ при вызове ResolveAll в замке Виндзор

Предположим, что в контейнере зарегистрировано несколько объектов, каждый из которых реализует один и тот же интерфейс:

container.Register(
    Component.For<ITask>().ImplementedBy<Task1>(),
    Component.For<ITask>().ImplementedBy<Task2>(),
    Component.For<ITask>().ImplementedBy<Task3>(),
    Component.For<ITask>().ImplementedBy<Task4>(),
);

И я хочу разрешить все реализации ITask:

var tasks = container.ResolveAll<ITask>();

Есть ли способ контролировать порядок разрешенных экземпляров?

Примечание: очевидно, я могу реализовать Order или же Priority свойство на ITask, и просто отсортировать список задач, но я ищу решение более низкого уровня.

2 ответа

Решение

Я считаю, что вам нужен Фильтр обработчиков, основанный на скудной документации и критических изменениях в Виндзорском замке 3; обеспечивает фильтрацию и сортировку компонентов. Вот выдержка из их вики-страницы

Интерфейс похож на IHandlerSelector, но позволяет фильтровать / сортировать обработчики, запрошенные методом container.ResolveAll().

Так что в основном вам нужно будет реализовать IHandlerFilter интерфейс, а затем добавить эту реализацию в ядро ​​при инициализации контейнера Windsor. Из исходного кода этот интерфейс выглядит примерно так...

public interface IHandlerFilter
{
    bool HasOpinionAbout(Type service);
    IHandler[] SelectHandlers(Type service, IHandler[] handlers);
}

Добавление фильтра обработчика в ядро ​​будет выглядеть примерно так:

 var container = new WindsorContainer()
        .Install(Configuration.FromXmlFile("components.config"));
        container.Kernel.AddHandlersFilter(new YourHandlerFilterImplementation());

а затем при разрешении всех компонентов служб с ResolveAll заказ будет отсортирован (и отфильтрован) на основе вашей собственной реализации

Второй совет Лео о том, что вам нужен фильтр обработчиков.

В моем блоге у меня есть пример того, как можно сделать простой фильтр обработчиков, который, в свою очередь, приводит к упорядоченным экземплярам задач, когда они разрешаются через ResolveAll<ITask> (или когда IEnumerable<ITask> впрыскивается):

class TaskHandlersFilter : IHandlersFilter
{
    readonly Dictionary<Type, int> sortOrder = 
        new Dictionary<Type, int>
        {
            {typeof (PrepareSomething), 1},
            {typeof (CarryItOut), 2},
            {typeof (FinishTheJob), 3},
        };

    public bool HasOpinionAbout(Type service)
    {
        return service == typeof(ITask);
    }

    public IHandler[] SelectHandlers(Type service, IHandler[] handlers)
    {
        // come up with some way of ordering implementations here
        // (cool solution coming up in the next post... ;))
        return handlers
            .OrderBy(h => sortOrder[h.ComponentModel.Implementation])
            .ToArray();
    }
}

У меня также есть более сложный пример, который работает с API, используемым для определения порядка - в этом случае я позволяю типам указывать свою позицию относительно другого типа, например, как

[ExecutesBefore(typeof(ExecutePayment))]
public class ValidateCreditCards : ITask { ... }

что может / не может быть полезным в вашей конкретной ситуации:)

Другие вопросы по тегам