3

我正在构建一个以 MVC3 作为主要前端的四层系统,但包含由服务层异步运行并报告进度的长时间运行的任务,MVV 将使用 Ajax 显示这些任务。我使用 Autofac 进行依赖注入 (DI) 主要是因为界面和文档很好,而且速度很快(请参阅Philip Mateescu关于DI 速度的出色研究)。

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

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

4

1 回答 1

7

更新 - 2014 年 6 月

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

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

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

以下是有关 MVC 中任务分配的其他一些说明,您可能会发现它们很有用:

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

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

我已经通过 Google Autofac 组找到了如何处理具有依赖关系的异步任务。事实证明,您可以访问 MVC 级别的容器,然后创建解析的新生命周期范围。有很多方法可以做到这一点,但Alex Meyer-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);
    }
  });
}

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

于 2012-06-12T09:12:09.217 回答