SignalR generates a hub for each method invoke ie onConnected, onDisconnect or any other methods on the hub. Autofac.SignalR all hub dependencies are resolved from the root container making them singletons.
I did find another solutions https://github.com/lethek/SignalR.Extras.Autofac but this required inheriting from a special lifetimehub, retro fitting this into an large existing solution would take a lot of work an re-testing.
The solutions below allows you to scope all dependencies per hub instance.
- Install-Package Autofac.SignalR
- Install-Package Castle.Core
public static class RegistrationExtensions
{
public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> RegisterHubActivator(this ContainerBuilder builder, params Assembly[] assemblies)
{
return builder.RegisterType<AutofacHubActivator>().As<IHubActivator>().SingleInstance();
}
}
public class AutofacHubActivator : IHubActivator
{
private readonly ILifetimeScope _lifetimeScope;
public AutofacHubActivator(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
public IHub Create(HubDescriptor descriptor)
{
var scope = _lifetimeScope.BeginLifetimeScope();
var hubType = descriptor.HubType;
var constructor = hubType.GetConstructors()
.Select(c => new { c, idx = c.GetParameters().Length })
.OrderByDescending(x => x.idx).Select(x => x.c)
.First();
var parameters = constructor.GetParameters().Select(parameterInfo => scope.Resolve(parameterInfo.ParameterType)).ToArray();
var generator = new ProxyGenerator();
return generator.CreateClassProxy(descriptor.HubType, ProxyGenerationOptions.Default, parameters, new DisposeInterceptor(scope)) as IHub;
}
}
public class DisposeInterceptor : StandardInterceptor
{
private readonly ILifetimeScope _lifetimeScope;
public DisposeInterceptor(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
protected override void PostProceed(IInvocation invocation)
{
if (invocation.Method.Name == "Dispose")
{
_lifetimeScope.Dispose();
}
base.PostProceed(invocation);
}
}