11

On the following page: http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection

Near the bottom (just below the text "RegisterHubs.Start") there is a piece of Ninject code that I am trying to reproduce using Autofac.

So far I have succeeded in giving myself a headache, but not much else. I have scoured the Autofac wiki, and the web for some help. Though, I am sure I probably missed some tidbit of information.

Update: Here is the relevant Ninject code on the page.

public static class RegisterHubs
{
    public static void Start()
    {
        var kernel = new StandardKernel();
        var resolver = new NinjectSignalRDependencyResolver(kernel);

        kernel.Bind<IStockTicker>()
            .To<Microsoft.AspNet.SignalR.StockTicker.StockTicker>()
            .InSingletonScope();

        kernel.Bind<IHubConnectionContext>().ToMethod(context =>
                resolver.Resolve<IConnectionManager>().
                    GetHubContext<StockTickerHub>().Clients
            ).WhenInjectedInto<IStockTicker>();

        var config = new HubConfiguration()
        {
            Resolver = resolver
        };

        App.MapSignalR(config);
    }
}

Update 2: Thought I would also add the objects trying to be composed.

public class StockTickerHub : Hub
{
    private readonly IStockTicker _stockTicker;

    public StockTickerHub(IStockTicker stockTicker) { }
}

public class StockTicker
{
    public StockTicker(IHubConnectionContext clients) { }
}
khellang
  • 17,550
  • 6
  • 64
  • 84
Obscured
  • 281
  • 5
  • 10
  • There are two `RegisterHubs.Start` in the article. Where do you get stuck? Please post your code. – Win Dec 12 '13 at 18:45
  • Have you managed to get it working? Did you use `GlobalHost` in order to get the IConnectionManager? – radu-matei Aug 17 '15 at 14:56

1 Answers1

12

Autofac does not have an equivalent of the WhenInjectedInto method. However, you could accomplish the same using named parameters.

Try something like this

using Autofac.Integration.SignalR;
using Microsoft.AspNet.SignalR.StockTicker;

public static class RegisterHubs
{
    public static void Start() 
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<StockTicker>()
            .WithParameter(ResolvedParameter.ForNamed("StockTickerContext"))
            .As<IStockTicker>()
            .SingleInstance();

        builder.Register(c => GlobalHost.DependencyResolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients)
            .Named<IHubConnectionContext>("StockTickerContext");

        var container = builder.Build();

        var resolver = new AutofacDependencyResolver(container);

        var config = new HubConfiguration { Resolver = resolver };

        App.MapSignalR(config);
    }
}

Note: The AutofacDependencyResolver comes from Autofac.Integration.SignalR.

Update: Ah, I missed a tiny detail from the linked page; the factory function for the IHubConnectionContext is using the resolver to get the IConnectionManager, and not the container itself (of course the container won't know about a IConnectionManager). I switched to use the default dependency resolver (GlobalHost.DependencyResolver) to get the IConnectionManager instead. That should work.

khellang
  • 17,550
  • 6
  • 64
  • 84
  • Thank you for your reply. I gave it a go, and thought it might do the trick. However, it is not hitting the constructors on either class. I will continue to try different things and see if I can figure it out. – Obscured Jan 14 '14 at 15:35
  • And you are absolutely sure that SignalR has been mapped correctly and you're hitting the correct path? What happens when you hit the `/signalr/hubs` route? – khellang Jan 14 '14 at 16:05
  • Sorry probably should have mentioned that earlier. Yes, I had this up and running without DI. I just wanted to switch to DI as an exercise. It might be way I am starting up? I had this in the signalr startup class. I will see if moving to global.asax/app_start may help. – Obscured Jan 14 '14 at 20:13
  • Here is the error message that I receive... iisexpress.exe Error: 0 : SignalR exception thrown by Task: System.AggregateException: One or more errors occurred. ---> Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency. – Obscured Jan 14 '14 at 21:07
  • Thank you! that was it. And the explanation was very helpful as well. I really appreciate the help. :) – Obscured Jan 15 '14 at 01:12
  • How to call App.MapSignalR from a console application? How to get a reference to IAppBuilder not using the SignalR Startup class? – Igor Kondrasovas May 13 '16 at 13:28
  • If you're self-hosting using a console app, you should look at http://www.asp.net/signalr/overview/deployment/tutorial-signalr-self-host – khellang May 13 '16 at 14:14