I have the following interface...
public interface IHandler<in TFor> where TFor : IRequest
{
void Handle(IEnumerable<TFor> requests);
}
which is typically implemented like so...
public class AssignmentHandler : HandlerBase, IHandler<AssignmentRequest>
{
public void Handle(IEnumerable<AssignmentRequest> assigmentRequests)
{
foreach(var request in assignmentRequests).....
}
}
IRequest
is simply a marker interface (at this point).
I register all handlers via conventions with the following...
public override void Load()
{
Kernel.Bind(x => x.FromAssemblyContaining<IHandler>()
.SelectAllClasses()
.InheritedFrom(typeof(IHandler<>))
.BindAllInterfaces());
//i also tried...
Kernel.Bind(x => x.FromAssemblyContaining<IHandler>()
.SelectAllClasses()
.InheritedFrom<IHandler<IRequest>>()
.BindSingleInterface());
}
and individually they resolve just fine.
There is one situation where i would like to resolve all handlers, and have them injected into a constructor like so...
public SomeConstructor(IEnumerable<IHandler<IRequest>> allHandlers)
This does not work and always returns empty.
My understanding is because i have registered them by convention as IHandler<ConcreteRequest>
, not IHandler<IRequest>
which is 2 distinct signatures.
How can i register all handlers by convention in a way that they will be identified collectively as IEnumerable<IHandler<IRequest>>
while also individually?
A 2nd registration is OK, but would much prefer resolution of one implementation via both signatures.
Not an answer to your question, but it seems to me that you're missing an abstraction, since all your handlers contain that same foreach loop, which means you're violating DRY. I suggest changing the interface to the following:
And have a generic implementation that allows handling multiple instances:
This removes the need for every handler to implement the foreach loop, and if the way the list should be processed ever changes, you only have to change it in a single place.
How to register this in Ninject, I unfortunately don't know.
UPDATE
With Simple Injector, the registration would simply be as follows: