Four variants of doing this are described in autofac documentation:
Option 1: Redesign Your Interfaces
When you run into a situation where you have a bunch of components
that implement identical services but they can’t be treated
identically, this is generally an interface design problem.
From an object oriented development perspective, you’d want your
objects to adhere to the Liskov substitution principle and this sort
of breaks that.
By doing some interface redesign, you don’t have to “choose a
dependency by context” - you use the types to differentiate and let
auto-wireup magic happen during resolution.
If you have the ability to affect change on your solution, this is the
recommended option.
Option 2: Change the Registrations
You can manually associate the appropriate type with the consuming component in that way:
var builder = new ContainerBuilder();
builder.Register(ctx => new ShippingProcessor(new PostalServiceSender()));
builder.Register(ctx => new CustomerNotifier(new EmailNotifier()));
var container = builder.Build();
// Lambda registrations resolve based on the specific type, not the
// ISender interface.
builder.Register(ctx => new ShippingProcessor(ctx.Resolve<PostalServiceSender>()));
builder.Register(ctx => new CustomerNotifier(ctx.Resolve<EmailNotifier>()));
var container = builder.Build();
Option 3: Use Keyed Services
builder.RegisterType<PostalServiceSender>()
.As<ISender>()
.Keyed<ISender>("order");
builder.RegisterType<EmailNotifier>()
.As<ISender>()
.Keyed<ISender>("notification");
builder.RegisterType<ShippingProcessor>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ISender),
(pi, ctx) => ctx.ResolveKeyed<ISender>("order")));
builder.RegisterType<CustomerNotifier>();
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ISender),
(pi, ctx) => ctx.ResolveKeyed<ISender>("notification")));
Option 4: Use Metadata
builder.RegisterType<PostalServiceSender>()
.As<ISender>()
.WithMetadata("SendAllowed", "order");
builder.RegisterType<EmailNotifier>()
.As<ISender>()
.WithMetadata("SendAllowed", "notification");
builder.RegisterType<ShippingProcessor>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ISender),
(pi, ctx) => ctx.Resolve<IEnumerable<Meta<ISender>>>()
.First(a => a.Metadata["SendAllowed"].Equals("order"))));
builder.RegisterType<CustomerNotifier>();
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ISender),
(pi, ctx) => ctx.Resolve<IEnumerable<Meta<ISender>>>()
.First(a => a.Metadata["SendAllowed"].Equals("notification"))));