Usare Ninject con un HUB di ASP.NET SignalR

di Marco De Sanctis, in ASP.NET 4.5, ASP.NET MVC,

Se la nostra applicazione sfrutta Ninject e utilizza la tecnica della dependency injection, probabilmente ci troveremo nella situazione in cui, anche nell'ambito di un Hub di ASP.NET SignalR, abbiamo bisogno di iniettare le dipendenze tramite il costruttore:

public class CustomersHub : Hub
{
  private ICustomerRepository _repository;
  public CustomersHub(ICustomerRepository repository)
  {
    if (repository == null)
      throw new ArgumentNullException("repository");

    _repository = repository;
  }

  // ...
}

In condizioni normali, questo Hub non è utilizzabile: ASP.NET SignalR, infatti, utilizza un dependency resolver simile a quello di ASP.NET MVC, che però per default non è configurato per sfruttare Ninject e quindi non è in grado di invocare il costruttore.

Dobbiamo quindi crearne uno personalizzato, che utilizzi questo container per risolvere la dipendenza da ICustomerRepository, e il modo più semplice è quello di creare una classe che erediti da DefaultDependencyResolver:

public class NinjectResolver : DefaultDependencyResolver
{
    private IKernel _kernel;
    public NinjectResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public override object GetService(Type serviceType)
    {
        var result = _kernel.TryGet(serviceType);

        if (result == null)
            return base.GetService(serviceType);

        return result;
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        var result = _kernel.GetAll(serviceType);

        return result.Union(base.GetServices(serviceType));
    }
}

L'idea di base è assolutamente simile al Dependency Resolver di ASP.NET MVC, ossia un oggetto che restituisca i componenti richiesti tramite i metodi GetService e GetServices. Andando nello specifico, l'implementazione che abbiamo realizzato sfrutta in prima istanza il kernel di Ninject per risolvere la dipendenza, sfruttando poi l'implementazione della classe base come fallback: è importante farlo perché comunque ASP.NET SignalR sfrutta questo resolver anche per costruire servizi interni di sistema, che non sono registrati su Ninject.

Per attivare questo resolver, è sufficiente specificarlo in fase di configurazione del routing:

public partial class Startup
{
  public void Configuration(IAppBuilder app)
  {
    ConfigureAuth(app);
    app.MapSignalR(new HubConfiguration() 
    {
      Resolver = new NinjectResolver(NinjectWebCommon.Kernel)
    });
  }
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi