使用带有SignalR的Autofac时的范围错误

我正在尝试在SignalR中心注入一个HttpContextBase

 public class EventHub : Hub, IDisconnect { private readonly HttpContextBase _httpContextBase; public EventHub(HttpContextBase httpContextBase) { _httpContextBase = httpContextBase; } [...] } 

注册码如下所示:

 private static void InitAutofac() { var builder = new ContainerBuilder(); var assembly = typeof (MvcApplication).Assembly; builder.RegisterControllers(assembly).PropertiesAutowired(); builder.RegisterModule(new AutofacWebTypesModule()); builder.RegisterFilterProvider(); builder.RegisterAssemblyTypes(assembly) .Where(InterfaceBasedInjectedClasses()) .AsImplementedInterfaces() .InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(assembly) .Where(InterfaceLessInjectedClasses()) .InstancePerLifetimeScope(); builder.RegisterType().InstancePerLifetimeScope(); builder.RegisterType().InstancePerLifetimeScope(); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); GlobalHost.DependencyResolver = new SignalR.Autofac.AutofacDependencyResolver(container); RouteTable.Routes.MapHubs(); } 

而我得到的错误是:

[DependencyResolutionException:从请求实例的作用域中看不到具有匹配’httpRequest’的标记的作用域。 这通常表示注册为每HTTP请求的组件正被SingleInstance()组件(或类似场景)重新请求。在Web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖,永远不会从容器本身请求]

堆栈跟踪:

 Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope) +160 Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable`1 parameters) +57 Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) +102 Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) +64 Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) +164 Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) +14 Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) +70 Autofac.ResolutionExtensions.TryResolve(IComponentContext context, Type serviceType, Object& instance) +70 SignalR.Autofac.AutofacDependencyResolver.GetService(Type serviceType) in D:\etc\Dev\SignalR.Autofac\AutofacDependencyResolver.cs:30 SignalR.Hubs.DefaultHubActivator.Create(HubDescriptor descriptor) +60 SignalR.Hubs.DefaultHubManager.ResolveHub(String hubName) +27 SignalR.Hubs.HubDispatcher.CreateHub(IRequest request, HubDescriptor descriptor, String connectionId, TrackingDictionary state, Boolean throwIfFailedToCreate) +445 SignalR.Hubs.HubDispatcher.OnReceivedAsync(IRequest request, String connectionId, String data) +246 SignalR.c__DisplayClass6.b__4(String data) +29 SignalR.Transports.ForeverTransport.ProcessSendRequest() +63 SignalR.Transports.ForeverTransport.ProcessRequestCore(ITransportConnection connection) +70 SignalR.Transports.ForeverTransport.ProcessRequest(ITransportConnection connection) +5 SignalR.PersistentConnection.ProcessRequestAsync(HostContext context) +560 SignalR.Hubs.HubDispatcher.ProcessRequestAsync(HostContext context) +120 SignalR.Hosting.AspNet.AspNetHandler.ProcessRequestAsync(HttpContextBase context) +422 SignalR.Hosting.AspNet.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +68 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

我刚刚开始使用autofac和SignalR,我发现自己有点陷入困境。 SO上的相关主题都没有帮助。 关于我做错了什么的任何想法?

问题是这一行:

 builder.RegisterModule(new AutofacWebTypesModule()); 

exception消息表明,在解析期间,正在尝试从标记为httpRequest的生命周期范围中解析httpRequest 。 当你注册InstancePerHttpRequest()时,你会在Autofac中获得这样的注册:

 // These two are roughly equivalent: builder.RegisterType().InstancePerHttpRequest(); builder.RegisterType().InstancePerMatchingLifetimeScope("AutofacWebRequest"); 

如果你看一下AutofacWebTypesModule的来源,它AutofacWebTypesModule web抽象(比如HttpContextBase ,你正在寻找的东西)注册为InstancePerHttpRequest

此外,如果查看Autofac.Integration.Mvc.AutofacDependencyResolver工作方式,无论何时在请求期间解析类型,它都会创建一个新的,嵌套的命名生命周期范围,标记为httpRequest 。 这允许你拥有那个神奇的InstancePerHttpRequest

假设你正在使用的SignalR.Autofac库就是这里的一个 ,也就是NuGet上的那个SignalR.Autofac.AutofacDependencyResolver ,在SignalR.Autofac.AutofacDependencyResolver没有为服务解析创建这样的嵌套/命名生命周期范围

因此,当Autofac尝试解析HttpContextBase依赖关系时,它无法找到httpRequest标记范围(因为它不存在)并发出您看到的错误。

对此没有简单的答案 。 嵌套的httpRequest范围实际上很重要,因为它基本上不能存在真实的Web请求之外。 它使它“安全” – 如果没有Web上下文(例如,在应用程序启动时),则无法获取HttpContextBase

如果你需要注入一个HttpContextBase并且你确定你的EventHub只能用于一个web请求,那就是它(我不是SignalR的人,所以请耐心等待),这意味着你需要:

  • 从SignalR.Autofac项目请求修复此问题。
  • 实现自己的自定义SignalR.Autofac.AutofacDependencyResolver,以MVC解析器的方式处理事物。

如果没有真正完成工作并自己测试,我无法真正提供有关如何实现这一目标的具体指导。 这个练习留给读者。