18

Do you know how to manually resolve dependencies in .net core? Something like

DependencyResolver.Resolve<ISomeService>()

UPDATE I'm in a class that was not injected, I want to resolve it from the inside, rather than pass variables all over the place

Liam
  • 27,717
  • 28
  • 128
  • 190
SexyMF
  • 10,657
  • 33
  • 102
  • 206
  • https://stackoverflow.com/a/32461714/3606250 – drizin Mar 03 '19 at 20:05
  • Does this answer your question? [Resolving instances with ASP.NET Core DI from within ConfigureServices](https://stackoverflow.com/questions/32459670/resolving-instances-with-asp-net-core-di-from-within-configureservices) – Liam Jul 15 '20 at 07:32
  • 2
    Just be aware that you're creating a maintenance nightmare, as you can no longer trust the dependencies injected via the constructor to be *all* the dependencies. It will invariably lead to test harnesses that have to set up every service for every test, just because you lost control over which services are needed. – Lasse V. Karlsen Jul 15 '20 at 07:42

2 Answers2

8

Add your dependency in ConfigureServices as below

public void ConfigureServices(IServiceCollection services){
    //AddSingleton or AddTransient based on your requirements
    services.AddTransient<ISomeService, ConcreteService>();
}

In your controller or anywhere, add IServiceProvider in the constructor like below:

using Microsoft.Extensions.DependencyInjection;

...

public class HomeController
{
  ...
  public HomeController(IServiceProvider serviceProvider)
  {
      var service = serviceProvider.GetService<ISomeService>();
  }
}

@Shazam, Here are some notes or suggestions based on your comment:

  • If you can not inject because you might not have a constructor in this class, I woud suggest to add a paramter to your function and pass the resolved dependency from outside

  • Another Idea is to add a static property and initialize its value in ConfigureServices

For Example:

public static class MyClass
{
    public static ISomeService MyServiceObj { set; get; }
    ....
}

In your ConfigureServices

   public void ConfigureServices(IServiceCollection services){
        services.AddTransient<ISomeService, ConcreteService>();
        MyClass.MyServiceObj = services.GetService<ISomeService>();
    }

Hope this helps, please rate my answer or leave me a comment if you still in doubt how to do it

Muhammad Soliman
  • 21,644
  • 6
  • 109
  • 75
  • 1
    At design time you should know which dependencies your controller would have, inject IServiceProvider seems a bad idea, I'd inject only the service I know I will need... – Juan Jun 03 '18 at 09:19
  • @Juan I did it in this way based on his question giving him the choice to manually inject what he needs but it seems he doesn't have constructor in his class, thanks though for your note – Muhammad Soliman Jun 03 '18 at 09:20
  • @Shazam If you can not inject I woud suggest to add a paramter to your function and pass the resolved dependency from outside – Muhammad Soliman Jun 03 '18 at 09:22
  • Another Idea is to add a static method and initialize its value after resolve in ConfigureServices – Muhammad Soliman Jun 03 '18 at 09:22
  • @msoliman can you please add more details on the last comments? Thanks – SexyMF Jun 03 '18 at 09:25
  • That could do the job, you expose a property, MyDependency, and form the class that instantiate the class that need that dependency you might inject, resolve and set that Dependency to your problematic class. – Juan Jun 03 '18 at 09:27
  • What if you don't have any controllers in your project? – Egor Pavlikhin Nov 20 '19 at 04:05
1

If you're trying to get scoped objects in a singleton object (like a BackgroundService), then serviceProvider.GetService method will raise an error stating this. The solution is getting IServiceProvider during construction then when needed (in this case ExecuteAsync) a new scope should be created and all needed objects should be created in this scope.

public class MyService:BackgroundService 
{
  private readonly IServiceProvider _serviceProvider;
  public MyService(IServiceProvider serviceProvider)
  {
    _serviceProvider = serviceProvider;
  }

  protected override Task ExecuteAsync(CancellationToken stoppingToken)
  {
    using (var scope = _serviceProvider.CreateScope())
    {
      var services = scope.ServiceProvider;            
      var logger = services.GetRequiredService<ILogger<MyService>>();
      logger?.LogInformation("MyService: ExecuteAsync");
      return Task.CompletedTask;
    }
  }
}
uuctum
  • 15
  • 4