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

前端 未结 3 1583
悲哀的现实
悲哀的现实 2020-12-05 17:15

Let us consider a service registration in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.A         


        
3条回答
  •  失恋的感觉
    2020-12-05 17:50

    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:

        public class ServiceCollection : IServiceCollection
        {
            private List _descriptors = new List();
        }
    

    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();
    Assert.True(service is FooA);
    
    var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IFoo));
    Assert.NotNull(descriptor);
    services.Remove(descriptor);
    
    service = services.BuildServiceProvider().GetService();
    Assert.Null(service);
    

    We finish with Replace extention method:

    services.Replace(ServiceLifetime.Transient);
    

    Its implementation:

    public static IServiceCollection Replace(
        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;
    }
    

提交回复
热议问题