使用Autofac管理终身范围

时间:2016-07-07 09:56:11

标签: c# asp.net-web-api2 owin autofac

上下文:Owin(自主)+ WebApi + UseAutofacMiddleware + UseAutofacWebApi

我要做的是:

在app启动容器中注册ILog实例。

对于每个请求,注册一个包含“root”实例的新ILog实例,以便每个中间件和/或每个请求服务都可以使用它。

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(log).As<ILog>();
containerBuilder.Register(ctx => {
    var rootLog = ctx.Resolve<ILog>();
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

然而,Autofac在实例化构造函数中具有ILog的中间件时会抱怨循环依赖。

如果我将“root log”命名为“root log”并使用给定名称解析,则一切都按预期工作。

containerBuilder.RegisterInstance(log)
                .Named("root", typeof(ILog));
containerBuilder.Register(ctx => {
    var rootLog = ctx.ResolveNamed<ILog>("root");
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

我是否被迫使用命名实例来使其工作?

1 个答案:

答案 0 :(得分:1)

Autofac 在组件请求服务时使用最新的注册服务。

在您的情况下,最新注册的ILog是lambda表达式:

containerBuilder.Register(ctx => {
    var rootLog = ctx.Resolve<ILog>();
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

这个lambda表达式请求ILog这是 Autofac 正在尝试构建的内容:这就是它检测循环依赖的原因。

避免循环依赖的最简单方法是让您的注册不依赖于自身。这是通过解析命名的ILog来做的,这是我推荐的解决方案。

在您的情况下,您也可以直接使用根日志而不解析它:

containerBuilder.RegisterInstance(rootLog).As<ILog>();
containerBuilder.Register(ctx => {
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();