Replace service registration in ASP.NET Core built-in DI container?

asp.net core dependency injection factory
.net core dependency injection with parameters
iservicecollection replace service
asp.net core get service provider
iserviceprovider replace service
asp.net core dependency injection without constructor
.net core register service at runtime
iservicecollection get service

Let us consider a service registration in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IFoo, FooA>();
}

Is it possible to change IFoo registration to FooB after AddTransient has been called? It can be helpful for testing purposes (for example, in TestStartup subclass) or if our access to codebase is limited.

If we register another IFoo implementation:

services.AddTransient<IFoo, FooA>();
services.AddTransient<IFoo, FooB>();

Then GetService<IFoo> returns FooB instead of FooA:

IFoo service = services.BuildServiceProvider().GetService<IFoo>();
Assert.True(service is FooB);

However, GetServices<IFoo> successfully returns both implementations (and the same for GetService<IEnumerable<IFoo>>):

var list = services.BuildServiceProvider().GetServices<IFoo>().ToList();
Assert.Equal(2, list.Count);

There is Remove(ServiceDescriptor) method in IServiceCollection contract. What should I do with ServiceDescriptor to modify a service registration?

Replace registered services in Asp.Net Core built-in DI Container , Recently I was doing some work related to asp.net identity where I need to replace Net Core Identity's default UserValidator logic with my own� If you want to replace registered services of built-in DI container then you can do that with Replace extension method of ServiceCollection. Recently I was doing some work related to asp.net identity where I need to replace Net Core Identity’s default UserValidator logic with my own custom logic (need to implement support for a duplicate

It is easy to override ASP.NET Core DI functionality if you know two simple things:

1. ServiceCollection is just a wrapper on top of List<ServiceDescriptor>:
    public class ServiceCollection : IServiceCollection
    {
        private List<ServiceDescriptor> _descriptors = new List<ServiceDescriptor>();
    }
2. When a service is registered, a new descriptor is added to list:
    private static IServiceCollection Add(
        IServiceCollection collection,
        Type serviceType,
        Type implementationType,
        ServiceLifetime lifetime)
    {
        var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
        collection.Add(descriptor);
        return collection;
    }

Therefore, it is possible to add/remove descriptors to/from this list to replace the registration:

IFoo service = services.BuildServiceProvider().GetService<IFoo>();
Assert.True(service is FooA);

var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IFoo));
Assert.NotNull(descriptor);
services.Remove(descriptor);

service = services.BuildServiceProvider().GetService<IFoo>();
Assert.Null(service);

We finish with Replace<TService, TImplementation> extention method:

services.Replace<IFoo, FooB>(ServiceLifetime.Transient);

Its implementation:

public static IServiceCollection Replace<TService, TImplementation>(
    this IServiceCollection services,
    ServiceLifetime lifetime)
    where TService : class
    where TImplementation : class, TService
{
    var descriptorToRemove = services.FirstOrDefault(d => d.ServiceType == typeof(TService));

    services.Remove(descriptorToRemove);

    var descriptorToAdd = new ServiceDescriptor(typeof(TService), typeof(TImplementation), lifetime);

    services.Add(descriptorToAdd);

    return services;
}

Dependency injection in ASP.NET Core, ASP.NET Core is designed from scratch to support Dependency Injection. interceptors, or decorators then you may replace built-in IoC container with a third NET Core allows us to register our application services with IoC container, in the� Registration of the dependency in a service container. ASP.NET Core provides a built-in service container, IServiceProvider. Services are registered in the app's Startup.ConfigureServices method. Injection of the service into the constructor of the class where it's used. The framework takes on the responsibility of creating an instance of the

Just to add on @ilya-chumakov 's great answer, here is the same method but with support for implementation factories

public static IServiceCollection Replace<TService>(
    this IServiceCollection services,
    Func<IServiceProvider, TService> implementationFactory,
    ServiceLifetime lifetime)
    where TService : class
{
    var descriptorToRemove = services.FirstOrDefault(d => d.ServiceType == typeof(TService));

    services.Remove(descriptorToRemove);

    var descriptorToAdd = new ServiceDescriptor(typeof(TService), implementationFactory, lifetime);

    services.Add(descriptorToAdd);

    return services;
}

in case we want to use it with a factory that instantiates the service like the following sample:

var serviceProvider = 
  new ServiceCollection()
    .Replace<IMyService>(sp => new MyService(), ServiceLifetime.Singleto)
    .BuildServiceProvider();

Dependency Injection in ASP.NET Core, NET Core is really easy with the built-in DI Container. You have to set the Implementation Type (the interface), the Service Type (the If you ever want to replace an already registered dependency, you can do it in ASP.NET� If you ever want to replace an already registered dependency, you can do it in ASP.NET Core dependency container. The Service Collection provides a Replace () method under Microsoft.Extensions.DependencyInjection.Extensions namespace which only accepts a ServiceDescriptor. services.Replace (ServiceDescriptor.Scoped<IFourService, FourService> ());

Using ServiceDescriptor To Register Dependencies In ASP.NET Core, NET Core dependency injection and how to customize it to use a different Until yet we have around 140 services registered to the IServiceCollection . To change to a different or custom DI container you need to replace the After that, the container gets built and stored in a property of type IContainer . I'm using ASP.NET Core's builtin DI container. It's missing some features I need, so I need to use a third-party container. The top ones on Nuget are Autofac and StructureMap. SimpleInjector is consistently the fastest, so I'm considering it too.

Customizing ASP.NET Core Part 3: Dependency Injection, ASP.NET Core provides a minimal feature set to use default services cotainer. But you IServiceProvider is the simple built-in container that is included in ASP. NET ASP.NET Core DI service provider, service collection and service registering lifestyle/lifetime. And last one, I can replace registered service with another. The main reason for those limitations to exist is because it's the goal of the built-in container to provide DI capabilities to especially the framework itself, while keeping its feature set to a minimum in the hope that more mature DI containers would be able to integrate with it. In other words, it tries to act as an Least-Common Denominator

ASP.NET Core Dependency Injection, NET Core, but has plenty of experience of the earlier versions of ASP. registered with the DI container when the application webhost is built. So a service registered as singleton should not depend on either a transient service or a scoped service Replacing the Built-in Dependency Injection Container. CreateFactory (typeof (TDecorator), new [] {typeof (TInterface)}); // replace the existing registration with one // that passes an instance of the existing registration // to the object factory for the decorator services.

Comments
  • Replace internally calls the same Add and Remove methods which I considered. It is a good addition anyway, thanks.
  • Another way (in less lines, but using the same methods); services.Replace(ServiceDescriptor.Transient<IFoo, FooB>());
  • Emdeded links = 404
  • @IbrarMumtaz They moved the DI out of ASP.NET Core into a separate library. I fixed the links.
  • how would you register mocked logger instance? or perhaps verify calls on the nulllogger?
  • How can we reflect the change of ServiceCollection to IServiceProvider?