Autofac SignalR 集成
SignalR 集成需要使用Autofac.SignalR NuGet 包。
SignalR 集成提供了对 SignalR 中心的依赖注入集成。由于 SignalR 的内部实现,不支持按请求生命周期的依赖。
除了这篇针对 Autofac 的文档外,您可能还对 微软关于 SignalR 和依赖注入的文档 感兴趣。
快速入门
要将 Autofac 与 SignalR 集成,您需要引用 SignalR 集成 NuGet 包,注册您的中心,并设置依赖解析器。
protected void Application_Start()
{
var builder = new ContainerBuilder();
// 注册您的SignalR中心。
builder.RegisterHubs(Assembly.GetExecutingAssembly());
// 将依赖解析器设置为Autofac。
var container = builder.Build();
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
}
下面的各部分会详细介绍这些功能如何工作以及如何使用它们。
注册中心
在应用程序启动时,在构建 Autofac 容器时,应注册您的 SignalR 中心及其依赖项。这通常发生在 OWIN 启动类中或 Global.asax
的 Application_Start
方法中。
var builder = new ContainerBuilder();
// 使用程序集扫描一次性注册所有中心...
builder.RegisterHubs(Assembly.GetExecutingAssembly());
// ...或者手动注册单个中心。
builder.RegisterType<ChatHub>().ExternallyOwned();
如果手动注册单个中心,请确保它们已注册为 ExternallyOwned()
。这样可以确保 SignalR 被允许控制中心的销毁,而不是 Autofac。
设置依赖解析器
在构建容器后,将其传递给 AutofacDependencyResolver
类的新实例。将新的解析器附加到 GlobalHost.DependencyResolver
(如果您使用 OWIN,则附加到 HubConfiguration.Resolver
)以便让 SignalR 知道它应该使用 AutofacDependencyResolver
来查找服务。这是 Autofac 实现 IDependencyResolver
接口的方式。
var container = builder.Build();
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
管理依赖生命周期
由于不支持按请求的依赖,为 SignalR 中心解析的所有依赖项都来自根容器。
- 如果您有
IDisposable
组件,它们将在应用程序的整个生命周期内存在,因为 Autofac 会在 直到生命周期范围/容器被丢弃 时保持它们。您应该将这些注册为ExternallyOwned()
。 - 任何注册为
InstancePerLifetimeScope()
的组件实际上都是单例。鉴于只有一个根生命周期范围,您只会得到一个实例。
为了使管理您的中心依赖生命周期更容易,可以在构造函数中将根生命周期范围注入到中心中。接下来,创建一个子生命周期范围,您可以在中心调用期间使用它来解析所需的项。最后,确保当中心由 SignalR 销毁时,也销毁子生命周期。(这类似于服务定位,但这是唯一获得 “按中心” 类型范围的方法。是的,它并不出色。)
public class MyHub : Hub
{
private readonly ILifetimeScope _hubLifetimeScope;
private readonly ILogger _logger;
public MyHub(ILifetimeScope lifetimeScope)
{
// 为中心创建一个生命周期范围。
_hubLifetimeScope = lifetimeScope.BeginLifetimeScope();
// 从中心生命周期范围解析依赖项。
_logger = _hubLifetimeScope.Resolve<ILogger>();
}
public void Send(string message)
{
// 您可以在这里使用依赖字段!
_logger.Write("Received message: " + message);
Clients.All.addMessage(message);
}
protected override void Dispose(bool disposing)
{
// 当中心被销毁时,丢弃中心生命周期范围。
if (disposing && _hubLifetimeScope != null)
{
_hubLifetimeScope.Dispose();
}
base.Dispose(disposing);
}
}
如果这是应用程序中的常见模式,您可能要考虑创建一个基类/抽象类,其他中心可以从该基类派生以节省所有复制粘贴创建/销毁范围的操作。
**将生命周期范围注入到您的中心并不会给您按请求的生命周期范围。**它只是让您以比从根容器中解析所有内容更主动的方式来管理依赖生命周期。即使使用这个解决方案,使用 InstancePerRequest
仍然会失败。有关更多信息,请参阅 关于按请求范围的 FAQ 。
OWIN 集成
如果您正在使用 SignalR 作为 OWIN 应用程序的一部分 ,则需要:
- 执行标准的 SignalR 集成所有操作——注册控制器、设置依赖解析器等。
- 使用 基于 Autofac OWIN 集成 设置您的应用。
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// 标准信号R设置:
// 获取您的HubConfiguration。在OWIN中,您将创建一个,而不是使用GlobalHost。
var config = new HubConfiguration();
// 注册您的SignalR中心。
builder.RegisterHubs(Assembly.GetExecutingAssembly());
// 将依赖解析器设置为Autofac。
var container = builder.Build();
config.Resolver = new AutofacDependencyResolver(container);
// OWIN信号R设置:
// 首先注册Autofac中间件,然后注册标准的SignalR中间件。
app.UseAutofacMiddleware(container);
app.MapSignalR("/signalr", config);
// 若要添加自定义HubPipeline模块,您必须从依赖解析器获取HubPipeline,例如:
var hubPipeline = config.Resolver.Resolve<IHubPipeline>();
hubPipeline.AddModule(new MyPipelineModule());
}
}
OWIN 集成中的常见错误是使用 GlobalHost
。**在 OWIN 中,您从头开始创建配置。**使用 OWIN 集成时,不应在任何地方引用 GlobalHost
。微软有关于此和其他 IoC 集成问题的文档。