我正在尝试在我的 SignalR 中心注入(inject) 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<SurvivalContainer>().InstancePerLifetimeScope();
builder.RegisterType<EventHub>().InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalHost.DependencyResolver = new SignalR.Autofac.AutofacDependencyResolver(container);
RouteTable.Routes.MapHubs();
}
我得到的错误是:
[DependencyResolutionException: No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.]
堆栈跟踪:
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.<ProcessRequestAsync>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());
异常消息表明,在解析期间,正在尝试从标记为 httpRequest
的生命周期范围内解析某些内容。当你注册一些东西时,你会在 Autofac 中得到这样的注册 InstancePerHttpRequest()
:
// These two are roughly equivalent:
builder.RegisterType<SomeType>().InstancePerHttpRequest();
builder.RegisterType<SomeType>().InstancePerMatchingLifetimeScope("AutofacWebRequest");
如果您查看 AutofacWebTypesModule
的源代码,它会将 Web 抽象(例如 HttpContextBase
,您正在寻找的东西)注册为 InstancePerHttpRequest
.
此外,如果您查看 Autofac.Integration.Mvc.AutofacDependencyResolver
的工作方式,每当您在请求期间解析类型时,它都会创建一个新的、嵌套的、命名的生命周期范围,标记为 http请求
。这使您可以拥有神奇的 InstancePerHttpRequest
。
假设您使用的 SignalR.Autofac
库是 the one here , 这也是 the one on NuGet ), 寻找 SignalR.Autofac.AutofacDependencyResolver
, 没有为服务解析创建这样的嵌套/命名生命周期范围。
因此,当 Autofac 尝试解析 HttpContextBase
依赖项时,它找不到 httpRequest
标记的范围(因为它不存在)并发出错误看见了。
对此没有简单的答案。嵌套的 httpRequest
范围实际上很重要,因为它基本上不能存在于真实 Web 请求的之外。它使它“安全”- 如果没有 Web 上下文(例如,在应用程序启动时),您将无法获得 HttpContextBase
。
如果您需要注入(inject)一个 HttpContextBase
并且您确定您的 EventHub
只会为一个网络请求而存在,仅此而已(我不是 SignalR 人,请耐心等待),这意味着您要么需要:
- 向 SignalR.Autofac 项目请求修复此问题。
- 实现您自己的自定义 SignalR.Autofac.AutofacDependencyResolver,以 MVC 解析器的方式处理事情。
如果没有实际完成工作并亲自测试,我无法真正提供有关如何完成该工作的具体指导。 这个练习留给读者。
关于c# - 将 Autofac 与 SignalR 结合使用时出现范围错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12802073/