【问题标题】:Scope error when using Autofac with SignalR将 Autofac 与 SignalR 一起使用时的范围错误
【发布时间】:2012-10-09 14:16:04
【问题描述】:

我正在尝试在我的 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<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” 请求。这通常表明一个组件注册为 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.<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上的相关主题都没有帮助。知道我做错了什么吗?

【问题讨论】:

    标签: c# asp.net-mvc-3 dependency-injection autofac signalr


    【解决方案1】:

    问题出在这一行:

    builder.RegisterModule(new AutofacWebTypesModule());
    

    异常消息表明,在解析期间,试图从标记为 httpRequest 的生命周期范围内解析某些内容。当您注册 InstancePerHttpRequest() 时,您会在 Autofac 中获得这样的注册:

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

    如果您查看AutofacWebTypesModule 的来源,它会将Web 抽象(如HttpContextBase,您正在寻找的东西)注册为InstancePerHttpRequest

    此外,如果您查看 Autofac.Integration.Mvc.AutofacDependencyResolver 的工作方式,每当您在请求期间解析类型时,它都会创建一个新的、嵌套的、命名的生命周期范围,并用 httpRequest 标记。这让你拥有魔法InstancePerHttpRequest

    假设您使用的SignalR.Autofac 库是the one here,也是the one on NuGet),查看SignalR.Autofac.AutofacDependencyResolver没有为服务创建这样的嵌套/命名生命周期范围分辨率

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

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

    如果您需要注入 HttpContextBase 并且您确定您的 EventHub 只能用于一个 Web 请求,仅此而已(我不是 SignalR 人,所以请耐心等待),这意味着您要么需要:

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

    如果不亲自完成这项工作并对其进行测试,我真的无法就如何完成这项工作提供具体指导。 这个练习留给读者。

    【讨论】:

    • 嗨,特拉维斯,谢谢,这很有用。我的印象是其他人已经完成了整个工作。我将不得不深入研究 autofac 和 SignalR,而不是我真正想要的,但让我们看看我是怎么做的。
    • 我很高兴地报告我使用alexmg.com/post/2010/11/04/… 和SignarR.Autofac.AutofacDependencyResolver(我不再使用它)的组合得到了一些工作。谢谢!
    猜你喜欢
    • 2015-10-28
    • 2020-04-25
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多