What would the Autofac equivalent to this Ninject code be?
Asked Answered
R

1

12

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) { }
}
Reconnoitre answered 11/12, 2013 at 1:52 Comment(2)
There are two RegisterHubs.Start in the article. Where do you get stuck? Please post your code.Repugn
Have you managed to get it working? Did you use GlobalHost in order to get the IConnectionManager?Familist
S
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.

Shalloon answered 14/1, 2014 at 13:51 Comment(7)
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.Reconnoitre
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?Shalloon
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.Reconnoitre
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.Reconnoitre
Thank you! that was it. And the explanation was very helpful as well. I really appreciate the help. :)Reconnoitre
How to call App.MapSignalR from a console application? How to get a reference to IAppBuilder not using the SignalR Startup class?Cedric
If you're self-hosting using a console app, you should look at asp.net/signalr/overview/deployment/tutorial-signalr-self-hostShalloon

© 2022 - 2024 — McMap. All rights reserved.