草庐IT

c# - Autofac - 无法创建请求生命周期范围,因为 HttpContext 不可用 - 由于异步代码?

coder 2024-05-22 原文

简短问题:Same as this unanswered problem

长问题:

我只是将一些代码从使用 Autofac 的 MVC 4 + Web Api 解决方案移植到我的新解决方案中,该解决方案也使用 Autofac 但仅使用 Web Api 2(没有 MVC 5.1 项目,只有一个 Web API)。

在我之前的解决方案中,我有 MVC4 和 Web Api,所以我有 2 个 Bootstrapper.cs 文件,每个文件一个。我只为新项目复制了 Web Api Bootstrap 。

现在我在新解决方案中有 2 个其他项目需要拉取依赖项。让我们假设我必须使用 DependencyResolver.Current.GetService<T>()尽管它是一种反模式。

起初这不起作用,直到我将 MVC 依赖解析器设置为同一个容器:

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

//I had to pull in Autofac.Mvc and Mvc 5.1 integration but this line fixed it
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

奇怪的是,这样做只会在其中一个项目中修复它!情况是这样的:

 Solution.Web project
      Bootstrapper.cs that registers both dependency resolvers for web api and mvc.

 Solution.ClassLib project
      var userRepo = DependencyResolver.Current.GetService<IUserRepo>(); //Good! :)

 Solution.WindowsWorkflow project
      var userRepo = DependencyResolver.Current.GetService<IUserRepo>(); //Throws exception :(

异常(exception)情况是: 无法创建请求生命周期范围,因为 HttpContext 不可用。

现在,在我们开始责备工作流之前,只知道我在另一个解决方案中进行了精确的设置,工作流能够很好地使用 DependencyResolver。所以我怀疑这与使用较新版本的 Autofac 以及工作流异步运行的事实有关(就像我链接到的关于异步代码的问题)

我尝试将所有注册码切换为使用 InstancePerLifetimeScope()而不是 InstancePerHttpRequest()并尝试创建一个范围:

using (var c= AutofacDependencyResolver.Current
                     .ApplicationContainer.BeginLifetimeScope("AutofacWebRequest"))
{
   var userRepo = DependencyResolver.Current.GetServices<IUserRepo>();
}

但它并没有改变异常。进一步分解代码就是真正的罪魁祸首:

var adr = AutofacDependencyResolver.Current; //Throws that exception 

真的需要过去这个花了太多时间的卡住。将在 2 天内奖励现有答案

最佳答案

2014 年 11 月 20 日更新:自此问题发布以来,Autofac.Mvc5 的版本中,AutofacDependencyResolver.Current 的实现已已更新,不再需要 HttpContext。如果您遇到此问题并找到此答案,您可以通过更新到更高版本的 Autofac.Mvc5 轻松解决问题。但是,我会完整地保留原始答案,以便人们理解为什么最初的提问者有问题。

原回答如下:


AutofacDependencyResolver.Current 需要一个 HttpContext

遍历代码,AutofacDependencyResolver.Current 如下所示:

public static AutofacDependencyResolver Current
{
  get
  {
    return DependencyResolver.Current.GetService<AutofacDependencyResolver>();
  }
}

当然,如果当前的依赖解析器 AutofacDependencyResolver 那么它会尝试做一个解析...

public object GetService(Type serviceType)
{
  return RequestLifetimeScope.ResolveOptional(serviceType);
}

它从 RequestLifetimeScopeProvider 获取生命周期范围...

public ILifetimeScope GetLifetimeScope(Action<ContainerBuilder> configurationAction)
{
  if (HttpContext.Current == null)
  {
    throw new InvalidOperationException("...");
  }

  // ...and your code is probably dying right there so I won't
  // include the rest of the source.
}

它必须像这样工作才能支持像 Glimpse 这样的工具动态包装/代理依赖解析器以便对其进行检测。这就是为什么不能将 DependencyResolver.Current 转换为 AutofacDependencyResolver 的原因。

几乎所有使用 Autofac.Integration.Mvc.AutofacDependencyResolver 的东西都需要 HttpContext

这就是您不断收到此错误的原因。 如果您没有注册 InstancePerHttpRequest 的依赖项也没关系 - AutofacDependencyResolver 仍需要网络上下文。

我猜您拥有的另一个工作流应用程序是 MVC 应用程序或始终存在 Web 上下文的东西。

以下是我的建议:

  • 如果您需要在 Web 上下文之外使用组件并且您在 WebApi 中,请使用 Autofac.Integration.WebApi.AutofacWebApiDependencyResolver
  • 如果您使用的是 WCF,请使用标准 AutofacHostFactory.Container 和主机工厂实现来解决依赖关系。 (WCF 的单例主机潜力等有点奇怪,因此“按请求”并不是那么简单。)
  • 如果您需要一些“不可知论”的技术,请考虑 Autofac 的 CommonServiceLocator 实现。它不会创建请求生命周期,但可能会解决一些问题。

如果您保持直截了当并且不尝试使用其本地栖息地之外的各种解析器,那么您应该不会遇到问题。

可以相当安全地在服务注册中交替使用InstancePerApiRequestInstancePerHttpRequest这两个扩展都使用相同的生命周期范围标记,因此 MVC Web 请求和 Web API 请求的概念可以被类似地对待,即使在一种情况下的基础生命周期范围是基于 HttpContext 而另一种情况是基于 IDependencyScope。因此,您可以假设跨应用程序/应用程序类型共享一个注册模块,它应该做正确的事情。

如果您需要原始的 Autofac 容器,请存储您自己对它的引用。不要假设 Autofac 会以某种方式返回该容器,如果您需要,您可能需要存储对您的应用程序容器的引用无论出于何种原因,稍后再获取。

public static class ApplicationContainer
{
  public static IContainer Container { get; set; }
}

// And then when you build your resolvers...
var container = builder.Build();
GlobalConfiguration.Configuration.DependencyResolver =
  new AutofacWebApiDependencyResolver(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
ApplicationContainer.Container = container;

这将为您省去很多麻烦。

关于c# - Autofac - 无法创建请求生命周期范围,因为 HttpContext 不可用 - 由于异步代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21804857/

有关c# - Autofac - 无法创建请求生命周期范围,因为 HttpContext 不可用 - 由于异步代码?的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  5. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  6. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  7. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  8. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  9. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  10. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

随机推荐