dove answer is fine but it is a bit confusing, adding another more specific answer.
My main goal is this to work:
[HubName("MyHub")]
public class MyHub : Hub
{
public IJobRepository JobRepository { get; }
public MyHub(IJobRepository jobRepository)
{
JobRepository = jobRepository ?? throw new ArgumentNullException(nameof(jobRepository));
}
...
}
Of course what you want is your Hubs to be created for you, they are usually created by SignalR but now that they have some dependencies SignalR cannot create them.
SignalR itself has a Dependency Resolver (in SignalR namespace) which uses to get its own dependencies, you can add stuff to it, but we want Windsor remember?
So we are going to change just how the IHubActivator
creates hubs, we are not going to use SignalR's but this one:
public class SignalRHubActivator : IHubActivator
{
private readonly IWindsorContainer _container;
public SignalRHubActivator(IWindsorContainer container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
var result = _container.Resolve(descriptor.HubType) as IHub;
if (result is Hub)
{
_container.Release(result);
}
return result;
}
}
To replace this in SignalR container you have to do something like:
// Get an instance of the hub creator (see note below)
var _hubActivator = new SignalRHubActivator(container);
// Get the SignalR's Default Dependency Resolver
var signalRResolver = new Microsoft.AspNet.SignalR.DefaultDependencyResolver();
// Override the IHubActivator service
signalRResolver.Register(typeof(IHubActivator), () => _hubActivator);
// now map SignalR with this configuration
appBuilder.MapSignalR(new HubConfiguration { Resolver = signalRResolver });
And that's it, you should also register all your Hubs with Windsor
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(Microsoft.AspNet.SignalR.Hub)));
...
container.Register(Component.For<IJobRepository>()).ImplementedBy<JobRepository>());
Note: I registered the SignalRHubActivator as a component too, this is because the Startup
class I use receives the activator as a dependency:
container.Register(Component.For<SignalRHubActivator>().
DependsOn(Dependency.OnValue("container", container)));