Assume that I have multiple objects registered in the 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 wish to resolve all the implementations of ITask:
var tasks = container.ResolveAll<ITask>();
Is there a way to control the order of the resolved instances?
Note: Obviously, I can implement an Order
or Priority
property on ITask, and just sort the list of tasks, but I am looking for a lower-level solution.
I believe that what you are looking for is a Handler Filter which based on the scarce documentation and the breaking changes in Windsor Castle 3; it provides filtering and sorting of components. Here's an extract from their Wiki page
The interface is similar to IHandlerSelector but allow you to filter/sort handlers requested by container.ResolveAll() method
So basically you will need to implement the IHandlerFilter
interface and then add this implementation to the kernel while initializing the Windsor container. From the source code, this interface looks something similar to this...
public interface IHandlerFilter
{
bool HasOpinionAbout(Type service);
IHandler[] SelectHandlers(Type service, IHandler[] handlers);
}
Adding the Handler Filter to the kernel would be something like below...
var container = new WindsorContainer()
.Install(Configuration.FromXmlFile("components.config"));
container.Kernel.AddHandlersFilter(new YourHandlerFilterImplementation());
and then when resolving all components of a services with ResolveAll
the order will be sorted (and filtered) based on your own implementation
I second Leo's advice that what you're after is a handlers filter.
On my blog I have this example on how a simple handlers filter can be made, which happens to be one that results in ordered task instances when they're resolved through ResolveAll<ITask>
(or when an IEnumerable<ITask>
gets injected):
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 elaborate example that plays around with the API used to specify the ordering - in this case, I'm allowing for the types to specify their position relative to another type, e.g. like
[ExecutesBefore(typeof(ExecutePayment))]
public class ValidateCreditCards : ITask { ... }
which might/might not be useful in your concrete situation :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With