简体   繁体   English

向Autofac指定要解析的命名服务

[英]Specify to Autofac which Named service to resolve

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: 现在,我有两个不同的命令处理程序(我有两个以上),并且每个命令处理程序都注入了一个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;
    }

}

How can I specify to CommandAHandler to get an instance of type "Write" and to CommandBHandler to get an instance of type "Read"? 如何指定CommandAHandler以获取类型为“ Write”的实例,并指定CommandBHandler以获取类型为“ Read”的实例? Using, of course, Autofac registration 当然使用Autofac注册

You are violating the Liskov Substitution Principle here (and therefore the SOLID principles). 您在这里违反了Liskov替代原则 (因此违反了SOLID原则)。 You have one 'abstraction' (ie DbContext ) but if you inject the readonly version into a consumer that expects the writable, the application will break. 您有一个“抽象”(即DbContext ),但是如果将只读版本注入到希望可写的使用者中,则应用程序将DbContext This is a strong indication that you are violating LSP. 这强烈表明您违反了LSP。

The LSP dictates that you have different abstractions for each case. LSP规定每种情况下您具有不同的抽象。 This basically means you should inject ReadContext and WriteContext directly. 这基本上意味着您应该直接注入ReadContext和WriteContext。 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>();

You can use lambda expression to register handlers into Ioc. 您可以使用lambda表达式将处理程序注册到Ioc中。 For example: 例如:

builder.Register(c => new CommandAHandler(c.Resolve<WriteContext>()));
builder.Register(c => new CommandBHandler(c.Resolve<ReadContext>()));

Assuming WriteContext and ReadContext are registered as DbContext : 假设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")
            )
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM