Order by calling ResolveAll in Castle Windsor

Suppose I have several objects registered in a container, all implementing the same interface:

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

And I want to enable all ITask implementations:

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

Is there a way to control the order of allowed instances?

Note. Obviously, I can implement the Order or Priority property in ITask and just sort the task list, but I'm looking for a lower level solution.

+5
source share
2 answers

I believe that what you are looking for is a Handler Filter , which is based on meager documentation and awesome changes in Windsor Castle 3; It provides filtering and sorting of components. Here is an excerpt from their Wiki page.

The interface is similar to IHandlerSelector, but allows you the filter / sort handlers requested by the container. Method ResolveAll ()

So, basically you need to implement the IHandlerFilter interface, and then add this implementation to the kernel when initializing the Windsor container. From the source code, this interface looks something like this ...

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

Adding a handler filter to the kernel will look something like this ...

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

and then when resolving all service components with ResolveAll order will be sorted (and filtered) based on your own implementation

+6
source

Leo’s second tip is that you use a handler filter.

In my blog, I have this example on how to make a simple filter for handlers , which, as it turned out, is the result that leads to ordered instances of the task when they are resolved using ResolveAll<ITask> (or when IEnumerable<ITask> is introduced):

 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(); } } 

I also have a more complex example that plays with the API used to indicate the order - in this case, I allow types to indicate their position relative to another type, for example like

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

which may / may not be useful in your specific situation :)

+3
source

Source: https://habr.com/ru/post/1205586/


All Articles