Sviatoslav V.
Sviatoslav V.

Reputation: 791

How to receive IHubContext out of Dependency Injected classes?

I want to send message from Service A using SignalR when some event occures (for example, message from Service B received). So hub method needs to be called from some sort of handler, that not constructed using Dependency Injection. How I can do this?

So far, I tried and read about the following things:

  1. I can inject context into Controller and lead it to my handler. I probably can do that, but passing hub context from the top (controller class) to the bottom (handler class) is not the best approach, which adds a lot of dependencies to the classes that should not be aware of this context, so I would like to avoid that.
  2. I can inject my IHubContext in "any" class, but then, the thing is, how to get an instance of that class on my handler?
  3. Add Static method to class with injected context!? Well, that works until you have 1 client because with new client static property is going to be overwritten.

So I cannot imagine, how handler can use dependency injected IHubContext.

Probably, someone did that before and have an example of how to truly inject context into any class.

Thank you in advance and any additional information will be provided, if necessary.

Upvotes: 3

Views: 3017

Answers (1)

Shahzad Hassan
Shahzad Hassan

Reputation: 1003

Answer 1

Here is one possible solution. Implement a factory pattern. Create a factory that knows how to create your handler. Inject the IHubContext in the factory. You can use a few approaches that way:

  1. Construct the Handler by passing in the IHubContext
  2. Create a public property in the Handler and set the IHubContext
  3. Create a method in the Handler and pass the IHubContext as a parameter

You can decide whichever approach suits you. Inject that factory in the controller via DI, and get the handler using the factory method. That way you are not exposing the IHubContext. Please see the code below

public interface IHandlerFactory
{
   Handler CreateHandler();
}

public class HandlerFactory : IHandlerFactory
{
    private IHubContext _hubContext;

    public HandlerFactory(IHubContext context)
    {
        _hubContext = context;
    }
    public Handler CreateHandler()
    {
        return new Handler(param1, param2, _context);
    }    
}

Then in the entry point, controller/service, inject the factory via DI

public class MyController : Controller
{
    private Handler _handler;

    public MyController(IHandlerFactory factory)
    {
        _handler = factory.CreateHandler();
    }
}

Then you can use that _handler in the other methods. I hope this helps.

Answer 2

Another possible solution is to use IHostedService if it's possible at all for you. Please see a solution to a GitHub issue, provided by David Fowler here, that I think somewhat relevant to your scenario.

Upvotes: 1

Related Questions