Заказ при вызове 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 { ... }
что может / не может быть полезным в вашей конкретной ситуации:)