Autofac - 混合InstancePerHttpRequest和异步范围

时间:2012-06-04 10:13:32

标签: asp.net-mvc-3 scope autofac

我正在构建一个以MVC3为主要前端的四层系统,但包含由服务层异步运行并报告进度的长期运行任务,MVV将使用Ajax显示。我使用Autofac进行依赖注入(DI)主要是因为接口和文档很好而且速度快(参见Philip Mateescu在DI speed上的这篇优秀研究)。

我的问题是如何设置Autofac来处理注入项的两个范围,即MVC3依赖项必须是PerHttpRequest,但异步任务依赖项必须是InstancePerLifetimeScope。

显然,服务层需要使用单独的DI来解决长时间运行的任务的依赖关系。这样做的最佳方式是什么?

1 个答案:

答案 0 :(得分:7)

更新 - 2014年6月

我已经更新了这个答案,因为使用AutoFac的最佳做法已经开始,加上MVC的变化。更改是AutoFac的最佳实践现在是通过使用.InstancePerLifetimeScope()后缀来定义在MVC HttpRequest的情况下需要持续访问整个生命周期的任何实例。请参阅下面的示例:

builder.RegisterType<MyDbContext>().As<IMyDbContext>().InstancePerLifetimeScope();

完成后,您不再需要在任务中指定要创建的新生命周期范围的名称(请参阅下面的原始答案,已更新)。

以下是一些关于MVC任务的其他注意事项,您可能会发现它们很有用:

  • 如果您正在使用新的async / await,那么不需要新的生命周期范围。 Aysnc / await保留当前上下文并简单地释放线程以提高负载下Web的性能。
  • 如果你真的想在后台运行某些东西然后加以警告 - 有一些问题。我建议你从异步的专家Stephen Cleary那里读到这个helpful blog post
  • 一个非常有用的组合是将SignalR与MVC结合使用来报告进度并允许用户取消。这对我来说效果很好。

原帖,但已更新(注意:您必须注册生命范围实例,如上所示)

我已经找到了如何通过Google Autofac组处理具有依赖关系的异步任务。事实证明,您可以访问MVC级别容器,然后创建解决方案的新生命周期范围。有很多方法可以做到这一点,但是Alex Meyer-Gleaves(他是专家)的这个answer提供了答案。 Alex建议使用以下代码来运行具有不同范围的任务。

public void Run<T>(Action<T> action)
{
  Task.Factory.StartNew(delegate
  {
    using (var container = AutofacDependencyResolver.Current
                           .ApplicationContainer.BeginLifetimeScope())
    {
        var service = container.Resolve<T>();
        action(service);
    }
  });
}

在Alex的帖子中有关于该主题的更详细的博客文章here的链接,这也非常有用。