使用 Autofac 管理生存期范围

本文关键字:范围 生存期 管理 Autofac 使用 | 更新日期: 2023-09-27 17:55:46

>上下文: Owin (self-host) + WebApi + UseAutofacMiddleware + UseAutofacWebApi

我想做的是:

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

对于每个请求,注册一个新的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时存在循环依赖关系。

如果我命名"根日志",并使用给定的名称解析,则一切按预期工作。

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

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

使用 Autofac 管理生存期范围

> 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();