使用Autofac与SignalR时误差范围(Scope error when using Auto

2019-08-01 06:57发布

我试图注入的HttpContextBase在我SignalR枢纽:

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:用标签匹配“的HttpRequest”没有范围是其中要求实例的范围可见。 这通常表示登记为每个HTTP请求的部件是由一个SingleInstance()成分reqested(或类似的情况。)在幅积分总是请求来自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.<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帮助。 在我做错了任何想法?

Answer 1:

问题是这样的一行:

builder.RegisterModule(new AutofacWebTypesModule());

异常消息表明,解析期间,一些试图从一生范围标记解决httpRequest 。 当你注册的东西你得到像这样的Autofac注册InstancePerHttpRequest()

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

如果你看一下源AutofacWebTypesModule它注册网络抽象(如HttpContextBase ,这件事你正在寻找)作为InstancePerHttpRequest

此外,如果你看的方式Autofac.Integration.Mvc.AutofacDependencyResolver工作,只要你的请求期间解决一个类型,它会创建一个新的,嵌套的,名为终身标记范围httpRequest 。 这可以让你有一个神奇的InstancePerHttpRequest

在此假设下的SignalR.Autofac你使用库是一个在这里 ,这也是对的NuGet的一个 ,看在) SignalR.Autofac.AutofacDependencyResolver正在为服务解决方案创建没有这样的嵌套/命名寿命范围

因此,当Autofac尝试解析HttpContextBase依赖性,它无法找到httpRequest标记的范围(因为它不存在)和问题,你看到的错误。

目前对此没有简单的答案 。 嵌套httpRequest因为它基本上不能真正的Web请求之外存在范围实际上是非常重要的。 它使“安全” -你不能得到一个HttpContextBase如果没有网络环境(比如,在应用程序启动)。

如果你需要注入一个HttpContextBase和你确定你的EventHub将只住了一个Web请求,这就是它(我不是SignalR的家伙,所以我承担),这意味着你要么需要:

  • 申请此修复从SignalR.Autofac项目。
  • 实现该处理的事情MVC解析器的方式做自己的自定义SignalR.Autofac.AutofacDependencyResolver。

而不实际做的工作,并测试它自己,我真的不能提供关于如何实现这一目标的具体指导。 这个练习留给读者。



文章来源: Scope error when using Autofac with SignalR