Autofac - 混合InstancePerHttpRequest和异步范围

Jon*_*ith 3 scope autofac asp.net-mvc-3

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

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

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

Jon*_*ith 7

更新 - 2014年6月

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

builder.RegisterType<MyDbContext>().As<IMyDbContext>().InstancePerLifetimeScope();
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

我已经找到了如何通过Google Autofac组处理具有依赖关系的异步任务.事实证明,您可以访问MVC级别容器,然后创建解决方案的新生命周期范围.有许多这样做的方法,但这个答案由亚历克斯·迈尔Gleaves(谁是专家)给出了答案.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);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

还有一个更详细的博客文章链接在这里对亚历克斯的帖子的主题,这也是非常有用的.