I have some SignalR hubs which may need to access some transient and singleton dependencies. Hooking the creation of the Hub is easy and works just fine however SignalR does it
I've had a bit similar problem but with Unity instead of Castle Windsor.
My requirements:
HierarchicalLifetimeManager
- child containers resolve and manage separate object instances. Registered like this:container.RegisterType<IMessageService, MessageService>(new HierarchicalLifetimeManager());
This is my solution:
[HubName("exampleHub")]
public class ExampleHub : Hub
{
IUnityContainer _container;
public CarrierApiHub(IUnityContainer container) // container itself injected in hub
{
_container = container.CreateChildContainer(); // child container derived from the main container.
}
public async Task<int> UnreadMessagesCount()
{
// Here i'm resolving instance of IMessageService which depends on
// other registrations specified on the container. Full object graph
// is constructed and destroyed on hub disposal.
var messageSvc = _container.Resolve<IMessageService>();
return await messageSvc.CountUnreadOf(UserId);
}
protected override void Dispose(bool disposing)
{
_container.Dispose(); // child container destroyed. all resolved objects disposed.
base.Dispose(disposing);
}
private int UserId
{
get
{
// only an example
var claim = ((ClaimsPrincipal)Context.User).GetClaim("user_id");
return int.Parse(claim.Value);
}
}
}
SignalR and dependency resolver configuration:
public static class ConfigureSignalR
{
public static void Initialize(UnityContainer unityContainer, IAppBuilder app)
{
app.Map("/signalr", map =>
{
var resolver = new AppSignalRDependencyResolver(unityContainer);
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJavaScriptProxies = false,
EnableJSONP = true, // Required for IE 9 (supports only polling)
Resolver = resolver
};
map.RunSignalR(hubConfiguration);
});
}
}
Dependency resolver implementation:
public class AppSignalRDependencyResolver : DefaultDependencyResolver
{
protected IUnityContainer _container;
public AppSignalRDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this._container = container.CreateChildContainer();
}
public override object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return base.GetService(serviceType);
}
}
public override IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType).Concat(base.GetServices(serviceType));
}
catch (ResolutionFailedException)
{
return base.GetServices(serviceType);
}
}
protected override void Dispose(bool disposing)
{
_container.Dispose();
base.Dispose(disposing);
}
}