First, you'll need to make sure your ICommandHandler<T>
is declared to support covariance:
public interface ICommandHandler<out T> { }
That out
is important or you won't be able to resolve all the ConsultantCommand
handlers at once. You'll also get an Autofac exception.
Next, use the Named
extension method to register your named service rather than doing it yourself. The syntax will look something like this:
builder.RegisterAssemblyTypes(assemblies)
.Where(t =>
t.IsClosedTypeOf(typeof(ICommandHandler<>)) &&
t.GetInterfaces()[0]
.GetGenericArguments()[0]
.IsAssignableTo<ConsultantCommand>())
.Named("name", typeof(ICommandHandler<ConsultantCommand>))
.InstancePerHttpRequest();
That registers all of the services that are ICommandHandler<T>
where T
derives from ConsultantCommand
as an ICommandHandler<ConsultantCommand>
. You have to use the base type or, again, you won't be able to resolve all the handlers at once. There isn't any method to "resolve all the services that derive from this base type." There's also no way to resolve a list of open generics.
When you resolve the list of handlers, you'll need to resolve a named IEnumerable<T>
:
using(var scope = container.BeginLifetimeScope())
{
var x =
scope.ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");
}
Of course, you're using InstancePerHttpRequest
so it'd be more like:
var x =
AutofacDependencyResolver
.Current
.RequestLifetimeScope
.ResolveNamed<IEnumerable<ICommandHandler<ConsultantCommand>>>("name");
As mentioned above, you have to register as a closed generic because this won't work:
// WON'T WORK:
scope.ResolveNamed<IEnumerable<ICommandHandler<>>>("name");
You can modify the registration and such as needed. The rest of the registration extensions should work as usual - if you want to register things as implemented interfaces or whatever else, it should work with RegisterAssemblyTypes
just like you were doing it with a single service.