Search code examples
c#asp.net-coredependency-injection

The service collection cannot be modified because it is read-only


I am using ASP.NET Core 8. I'm trying to resolve a dependency at app start up and then use it to manually register a second dependency.

But I am getting this error

The service collection cannot be modified because it is read-only

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// REGISTER FIRST DEPENDENCY
builder.Services.AddTransient<IMyDependency, MyDependency>(); 

var app = builder.Build();

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

    // RESOLVE FIRST DEPENDENCY
    var myDependency = services.GetRequiredService<IMyDependency>(); 

    // ERROR: The service collection cannot be modified because it is read-only
    builder.Services.AddTransient<IAnotherDependency>(srv => new AnotherDependency(myDependency));
}

How could I get this to work?


Solution

    1. Why occurring this error:

    In ASP.NET Core, IServiceCollection is used to register various services within the application. Once the BuildServiceProvider() method is called to construct an IServiceProvider, the IServiceCollection becomes read-only. This is done to ensure that service registrations cannot be modified or disrupted during the runtime of the application.

    1. Solution:

    Services are added to the DI container with WebApplicationBuilder.Services, builder.Services. You can achieve this just need to register them both in the container.

    You can register the IMyDependency service first, then register the IAnotherDependency service. Use a lambda expression as a parameter during the registration of IAnotherDependency to resolve the IMyDependency service. This way, you can implement the instantiation of IAnotherDependency which depends on the IMyDependency service:

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddTransient<IMyDependency, MyDependency>(); // REGISTER FIRST DEPENDENCY
    
    builder.Services.AddTransient<IAnotherDependency>(srv =>
    {
        var myDependency = srv.GetRequiredService<IMyDependency>(); // resolve first dependency
        return new AnotherDependency(myDependency);
    });
    
    var app = builder.Build();