Reputation: 6973
I have two different services (Entity Framework contexts) that I inject all over my application and registered as following:
builder.Register<WriteContext>().Named("Write");
builder.Register<ReadContext>().Named("Read");
Now, I have two different command handlers (I have more than two) and each one gets injected a DbContext
as following:
public class CommandAHandler : ICommandHandler {
private readonly DbContext context;
// this handler should get "Write" context
public CommandAHandler(DbContext context) {
this.context = context;
}
}
public class CommandBHandler : ICommandHandler {
private readonly DbContext context;
// this handler should get "Read" context
public CommandBHandler(DbContext context) {
this.context = context;
}
}
How can I specify to CommandAHandler to get an instance of type "Write" and to CommandBHandler to get an instance of type "Read"? Using, of course, Autofac registration
Upvotes: 2
Views: 529
Reputation: 172646
You are violating the Liskov Substitution Principle here (and therefore the SOLID principles). You have one 'abstraction' (i.e. DbContext
) but if you inject the readonly version into a consumer that expects the writable, the application will break. This is a strong indication that you are violating LSP.
The LSP dictates that you have different abstractions for each case. This basically means you should inject ReadContext and WriteContext directly. This will immediately solve your registration problem, because you can define your handlers as:
public CommandAHandler(WriteContext context)
public CommandBHandler(ReadContext context)
This allows you to simplify your registration to the following:
builder.Register<WriteContext>();
builder.Register<ReadContext>();
Upvotes: 2
Reputation: 1570
Assuming WriteContext
and ReadContext
are registered as DbContext
:
builder
.RegisterType<CommandAHandler>()
.WithParameters(
new[] {
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(DbContext),
(pi, ctx) => ctx.ResolveNamed<DbContext>("Write")
)
});
builder
.RegisterType<CommandBHandler>()
.WithParameters(
new[] {
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(DbContext),
(pi, ctx) => ctx.ResolveNamed<DbContext>("Read")
)
});
Upvotes: 0
Reputation: 9519
You can use lambda expression to register handlers into Ioc. For example:
builder.Register(c => new CommandAHandler(c.Resolve<WriteContext>()));
builder.Register(c => new CommandBHandler(c.Resolve<ReadContext>()));
Upvotes: 1