指定Autofac要解析的命名服务

时间:2016-12-14 12:34:56

标签: c# autofac

我有两个不同的服务(实体框架上下文),我在我的应用程序中注入并注册如下:

builder.Register<WriteContext>().Named("Write");
builder.Register<ReadContext>().Named("Read");

现在,我有两个不同的命令处理程序(我有两个以上),每个都注入一个DbContext如下:

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;
    }

}

如何指定CommandAHandler来获取类型&#34的实例;写&#34;和CommandBHandler获取类型&#34的实例;阅读&#34;?当然,使用Autofac注册

3 个答案:

答案 0 :(得分:2)

您违反了此处的Liskov Substitution Principle(因此也违反了SOLID原则)。你有一个'抽象'(即DbContext),但是如果你将只读版本注入一个期望可写的消费者,应用程序就会中断。这强烈表明您违反了LSP。

LSP规定每个案例都有不同的抽象。这基本上意味着你应该直接注入ReadContext和WriteContext。这将立即解决您的注册问题,因为您可以将处理程序定义为:

public CommandAHandler(WriteContext context)
public CommandBHandler(ReadContext context)

这使您可以将注册简化为以下内容:

builder.Register<WriteContext>();
builder.Register<ReadContext>();

答案 1 :(得分:1)

您可以使用lambda表达式将处理程序注册到Ioc中。例如:

authentication entry point

答案 2 :(得分:0)

假设WriteContextReadContext注册为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")
            )
        });