25

I know how to do dependency injection in the Startup.cs in .NET 5 (or before), but how do I do the same with the top-level Program.cs in .NET 6?

.NET 5: for example, I can inject a class in the Configure method

public class Startup
{
    public IConfiguration _configuration { get; }
    public IWebHostEnvironment _env { get; set; }

    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        _configuration = configuration;
        _env = env;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        // TODO
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IToInjectService serviceToInject)
    {
        // USE SERVICE
    }
}

How can I achieve this in .NET 6?

Maarten Vissers
  • 499
  • 1
  • 4
  • 11

5 Answers5

36

Using .Net 6 is easy. Just execute GetService method after configure app services and have ran Build method.

WebApplication? app = builder.Build();

var someService = app.Services.GetService<ISomeService>();

someService.DoSomething();
Edu_LG
  • 1,500
  • 1
  • 13
  • 11
  • 5
    Any chance of getting them *before* `builder.Build()`? – Simone Oct 27 '22 at 14:48
  • I don't know if is possible – Edu_LG Nov 02 '22 at 07:25
  • 1
    "SomeService" didn't work for me. But "ISomeService" works. In other words, use the interface with the GetService method. – thd Jan 20 '23 at 15:18
  • Off course, "SomeService" is the interface. Is just an example, a word. – Edu_LG Jan 23 '23 at 07:24
  • Use `SomeService` if it has no interface or if the DI registration was done without the interface. (_Why are you skipping an interface?_) Use `ISomeService` if the service was registered for DI using the interface. – Zarepheth Apr 17 '23 at 15:55
15

You add your service to the builder.Services collection and then access it with

var myService = services.BuildServiceProvider().GetService<MyService>();
Wim Ombelets
  • 5,097
  • 3
  • 39
  • 55
  • 1
    Maybe use `CreateScope()` to create a scope if the `MyService` is scoped. – Tvde1 Apr 15 '22 at 09:35
  • @Tvde1 that's right – Wim Ombelets Apr 15 '22 at 09:36
  • 2
    `var myService = services.BuildServiceProvider().CreateScope().ServiceProvider.GetRequiredService();` if I recall correctly – Tvde1 Apr 15 '22 at 09:39
  • @MaartenVissers that's undoubtedly answered elsewhere but it's not unimportant so just look up scoped services in your preferred search engine. – Wim Ombelets Apr 15 '22 at 09:39
  • 4
    So calling BuildServiceProvider is really not recommended. It creates additional copies of singleton services. – Saturn K Jun 27 '22 at 15:56
  • @SaturnK where does OP say this is a singleton service? – Wim Ombelets Jun 27 '22 at 19:17
  • 1
    @WimOmbelets if this is the only service that's ever going to be in the code, then yes, but this handicaps the code in case there is ever a singleton service registered in the App/API now or in the future. As I mentioned, if or more than likely, when there is a singleton service, this would create additional copies. It's an anti-pattern. – Saturn K Jun 28 '22 at 20:50
  • @SaturnK Be that as it may, there are situations you may find yourself in, where there simply isn't any viable alternative and, as an unfortunate side-effect of the DI implementation in .net, does cause multiple caches of singleton instances to be called into existence. AFAIK, the workarounds all point to one smell replacing another so if you have a surefire solution to this, feel free to look up the relevant questions here on SO and post your answer. – Wim Ombelets Jun 28 '22 at 21:46
  • @WimOmbelets, the better solution is already answered below by @Edu_LG. You use `var builder = WebApplication.CreateBuilder(args);` which replaces the ConfigureServices(), then you do `var application = builder.Build();` and then `var service = application.Services.GetService` or `var service = application.Services.GetRequiredService` and that indeed does not have a code smell. – Saturn K Jun 28 '22 at 21:56
  • 1
    This should not be the selected answer, as this is causing a potential further problem with dependencies being registered twice. This dependency should be retrieved from the already Built web application builder `builder.Build();` – Hawkzey Aug 28 '22 at 14:12
  • All of the comments here including suggestions involving `builder.Build()` fail to address a situation where you need to access the injected service before calling `builder.Buid()`, e.g. when configuring another service being added to the DI container. So far, this answer is the only one I've come across that facilitates this, although I accept that it may be bad practice in the case of singleton services. If there's an alternative solution I'd love to hear it! – Philip Stratford Jun 13 '23 at 21:23
11

If you need to use a scoped service at start, this is how your program.cs should looks like:

var builder = WebApplication.CreateBuilder(args);

//Add the service
builder.Services.AddScoped<IMyDependency, MyDependency>();

var app = builder.Build();

using (var serviceScope = app.Services.CreateScope())
{
    var services = serviceScope.ServiceProvider;

    var myDependency = services.GetRequiredService<IMyDependency>();

    //Use the service
    myDependency.DoSomething();

}

app.Run();

from: Resolve a service at app start up

it did work for mi DbInitializer

Sergio Galarza
  • 111
  • 2
  • 4
6

Inside the program.cs file you can manage your services by builder.Services

For example, I added DbContext and Two different services based on the Singleton pattern and Scoped

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddDbContext<MyDbContext>(options =>
{
    // options.UseSqlServer(...);
});
builder.Services.AddSingleton<IMyService, MyService>();
builder.Services.AddScoped<IMySessionBasedService, MySessionBasedService>();

For more information check Code samples migrated to the new minimal hosting model in ASP.NET Core 6.0

Reza Heidari
  • 1,192
  • 2
  • 18
  • 23
1

I tried to use the GetService method but I pass the service interface type as input (as shown below) and this worked with me.

var app = builder.Build();    
var injectedService1 = app.Services.GetService<IToInjectService>();
injectedService1.DoSomething();
Mohammed Osman
  • 3,688
  • 2
  • 27
  • 25