【问题标题】:Injecting dependencies for SignalR Hubs using autofac in in MVC 5 application在 MVC 5 应用程序中使用 autofac 为 SignalR Hub 注入依赖项
【发布时间】:2014-04-06 17:32:27
【问题描述】:

我正在尝试将 SignalR 2 引入现有项目,其中所有依赖项注入都使用 autofac 执行,所有依赖项配置都在 Global.asax 中执行。我找到了 Autofac.SignalR 包,用于将 SignalR 与 autofac 及其 accompanying documentation 一起使用。

我遵循了提供的文档中的示例,并遵循了使用 RegisterHubs 函数而不是定义我的个人集线器依赖项的建议。

不幸的是,我的 Hub 类在尝试解决来自生命周期范围的依赖项时出现以下运行时错误

Autofac.Core.DependencyResolutionException was unhandled by user code
HResult=-2146233088
Message=No scope with a Tag matching 'AutofacWebRequest' is
visible from the scope in which instance was requested.
This generally indicates that a component registered as per-HTTP
request is being requested 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.

我无法让 DependencyResolver.Current 或 ILifeTimeScopeProvider 为我工作。

我的依赖配置如下

var builder = new ContainerBuilder();
    .RegisterControllers(typeof (MvcApplication).Assembly);
    .RegisterHubs(Assembly.GetExecutingAssembly());
    ...
var container = builder.Build();

// Set dependency resolver for MVC
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

// Set dependency resolver for Web API
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

// Set the dependency resolver for SignalR
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

var signalRDependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);
GlobalHost.DependencyResolver = signalRDependencyResolver;

我也按照例子设置了我的hub类:

public class BaseHub : Hub
{
    protected readonly ILifetimeScope _hubLifetimeScope;
    private static IUserSignalRConnectionRepository _userSignalRConnectionRepository;

    public BaseHub(ILifetimeScope lifetimeScope) : base()
    {
        _hubLifetimeScope = lifetimeScope.BeginLifetimeScope();

        _userSignalRConnectionRepository = _hubLifetimeScope.Resolve<IUserSignalRConnectionRepository>();
    }

    protected override void Dispose(bool disposing)
    {
        // Dipose the hub lifetime scope when the hub is disposed.
        if (disposing && _hubLifetimeScope != null)
            _hubLifetimeScope.Dispose();

        base.Dispose(disposing);
    }
}

异常发生在cub类就行了

_userSignalRConnectionRepository = _hubLifetimeScope.Resolve<IUserSignalRConnectionRepository>();

【问题讨论】:

    标签: asp.net-mvc dependency-injection signalr autofac signalr-hub


    【解决方案1】:

    您应该包含注册 IUserSignalRConnectionRepository 的代码。

    错误消息似乎表明此依赖项是使用InstancePerHttpRequest() 注册的,相当于InstancePerMatchingLifetimeScope("AutofacWebRequest")。这个范围是在 MVC 请求的情况下为您自动创建的,但不是为 SignalR 请求创建的(这可能是一件好事,因为它们可以无限期地持续下去)。

    您可以通过调用lifetimeScope.BeginLifetimeScope("AutofacWebRequest"); 来解决这个问题。而不是您的 Hub 构造函数中的 lifetimeScope.BeginLifetimeScope();

    或者,您可以使用InstancePerDependency()(默认设置)或SingleInstance()而不是InstancePerHttpRequest()来注册IUserSignalRConnectionRepository。

    【讨论】:

    • 谢谢。您是正确的,IUserSignalRConnectionRepository 正在与我们的其他存储库一起注册为 InstancePerHttpRequest()。您使用lifetimeScope.BeginLifetimeScope("AutofacWebRequest"); 的解决方法;似乎工作。将我的存储库接口注册为 InstancePerDependency() 或 SingleInstance() 而不是使用解决方法会有优势吗?我有一些依赖项,我想从集线器和 MVC 类中引用它们,所以如果我可以做一个适用于两者的注册,那将是理想的。
    • 我认为使用InstancePerHttpRequest()然后使用lifetimeScope.BeginLifetimeScope("AutofacWebRequest")就可以了。我认为这与使用 InstancePerDependency() 没有什么不同,因为它只在每个范围内解析一次。我应该补充一点,SignalR 为每个调用实例化一个新的集线器,该集线器与 Web 请求不是一对一对应的。在 WebSockets 的情况下,一个请求负责许多调用。我认为这并不重要,除非您的 IUserSignalRConnectionRepository 依赖于每个实际请求创建一次。
    • 不,尽可能不频繁地实例化 IUserSignalRConnectionRepository 是理想的。它是我需要构建的自定义 SignalR 背板的一部分,以使用我们的 MongoDB 数据存储库跟踪负载平衡服务器场中的用户 SignalR 连接,因此应该可以正常工作。我会密切关注垃圾收集,但只是为了确保一切都得到妥善清理。这种依赖本身可能会被重构,但我的一些集线器会有类似的依赖。
    • 如果您尝试尽可能少地实例化 IUserSignalRConnectionRepository,您可能希望使用 SingleInstance() 注册它。这将导致 IUserSignalRConnectionRepository 在您的应用程序的整个生命周期中在第一次解析时被实例化一次。任何时候它被解决后,原始实例将被返回。如果您这样做,您的 Hub 代码无需更改即可调用lifetimeScope.BeginLifetimeScope("AutofacWebRequest")。
    猜你喜欢
    • 1970-01-01
    • 2021-10-13
    • 2018-06-16
    • 2020-11-30
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多