【问题标题】:AutoFac+WebAPI not disposing objectsAutoFac+WebAPI 不处理对象
【发布时间】:2014-04-15 10:32:23
【问题描述】:

我有以下代码来构建依赖项:

private static void InitializeContainer(HttpConfiguration config)
{
    var builder = new ContainerBuilder();
    var controllers = AssemblyUtils.GetAssemblies(true);

    controllers.Add(Assembly.GetExecutingAssembly());

    builder.RegisterApiControllers(controllers.ToArray()).PropertiesAutowired();

    builder
        .RegisterAssemblyTypes(
            new List<Assembly>(AssemblyUtils.GetAssemblies(false))
            {
                Assembly.GetExecutingAssembly()
            }.ToArray())
        .Where(t =>
            t.GetCustomAttributes(typeof(IocContainerMarkerAttribute), false).Any() ||
            t.IsSubclassOf(typeof(HandlerAspectAttribute)) ||
            typeof(ICoreContract).IsAssignableFrom(t))
        .AsImplementedInterfaces().InstancePerDependency()
        .PropertiesAutowired().OwnedByLifetimeScope();

    var container = builder.Build();

    GlobalConfiguration.Configuration.DependencyResolver =
       new AutofacWebApiDependencyResolver(container);

    config.DependencyResolver =
        GlobalConfiguration.Configuration.DependencyResolver;
}

处理程序:

public class ArchieveDocumentCommandHandler 
    : IHandler<ArchieveDocumentCommand>, IDisposable
{
    public IServiceMessageDispatcher Dispatcher { get; set; }
    public IDocumentRepository DocumentRepository { get; set; }
    public IFileSystemProvider FileSystemProvider { get; set; }
    public ICoreSettingRepository CoreSettingRepository { get; set; }

    public void Handles(ArchieveDocumentCommand message) { }

    public void Dispose() { }
}

但不知何故,Autofac 并没有在请求完成后调用对象中的Dispose 方法。我读到了生命周期范围,但由于在这种情况下是 Autofac 管理范围,所以我无法理解发生了什么。

我在这里做错了吗?

更新

public class CommandsController : ApiController
{
    [HttpPost]
    public HttpResponseMessage Deliver()
    {
    ...

        var handler = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(ICommandValidator<>).MakeGenericType(message.GetType()));

        if (handler == null)
        {
            return new Dictionary<string, string>();
        }

        return (Dictionary<string, string>)handler.GetType()
            .InvokeMember("ValidateCommand", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, handler, new object[] { message });
    }
}

另外,我使用的 autofac web api 版本是:3.1.1 这也破坏了一些现有的功能:

这样的控制器:

public class AProtectedReadModelController : ApiController
{ }

public class AssessmentController : AProtectedReadModelController
{
    [Route("queries/risk/assessment")]
    [HttpGet]
    public ProcessInitialScreenModel GetProcessInitialScreen()
    {
        return ...;
    }
}

未加载。

【问题讨论】:

  • 您能否确认 Autofac 正在 WebAPI 之外正确处理处置?
  • 我为什么要这样做?我需要它来使用 WebAPI。
  • 你能告诉我们什么正在消耗处理程序以及它的生命周期范围是什么?我很好奇对象是否保持活力,因为依赖它的东西正在保持活力。例如,如果使用处理程序的事物是单例,则处理程序将在根生命周期范围内解析,并且在根范围清理之前不会被清理。
  • @TravisIllig 在通用控制器中使用的处理程序将发布代码示例。谢谢

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


【解决方案1】:

您遇到的挑战是因为您试图直接在 DependencyResolver 之外解析对象,而不是使用请求生命周期范围。

当您使用 Web API 时,“请求生命周期范围”由入站请求消息管理。当您从根 DependencyResolver 解决某些问题时,它会在应用程序/顶层解决,而不是作为请求的一部分。这就是为什么您没有看到任何处置的原因 - 因为拥有的生命周期范围没有被处置,因为拥有的生命周期范围是在根级别。

我有一个关于请求生命周期范围的长时间讨论作为这个问题的答案:Transitioning to AutofacWebApiDependencyResolver from MVC's DependencyResolver - Where is .Current?

虽然其他问题涉及测试场景,但它的答案仍然适用 - 如果您需要手动解决某些问题(如果可能,我建议您不要这样做 - 服务位置不是那么好),那么您需要做所以超出了与请求消息关联的请求范围。

// In the controller...
var validatorType = typeof(ICommandValidator<>)
                      .MakeGenericType(message.GetType());
var handler = this.Request
                  .GetDependencyScope()
                  .GetService(validatorType);

【讨论】:

  • 非常感谢您的帮助。现在我明白了为什么当我尝试使用 InstancePerApiRequest 时会得到一个空范围。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-22
  • 2011-05-09
相关资源
最近更新 更多