项目需要重构某个包中的某一个功能
把源码拿下来之后发现需要重写其中一个服务
但是因为该服务访问级别为internal, 需要把原来internal服务从service collection注册器中移除
注入重写之后的服务
ASP.NET Core中的DI容器最终体现为一个IServiceProvider接口, 我们将所有实现了该接口的类型及其实例统称为ServiceProvider, 它仅仅提供了唯一个GetService方法,该方法根据提供的服务类型为你提供对应的服务实例
ASP.NET Core内部真正使用的是一个实现了IServiceProvider接口的内部类型(该类型的名称为“ServiceProvider”), 我们不能直接创建该对象,只能间接地通过调用IServiceCollection接口的扩展方法BuildServiceProvider得到它。IServiceCollection接口定义在“Microsoft.Extensions.DependencyInjection”命名空间下
IServiceCollection接口实际上代表一个元素为ServiceDescriptor对象的集合,它直接继承了另一个接口IList,而ServiceCollection类实现了该接口。
体现为DI容器的ServiceProvider之所以能够根据我们给定的服务类型(一般是一个接口类型)提供一个能够开箱即用的服务实例,是因为我们预先注册了相应的服务描述信息,这些指导ServiceProvider正确实施服务提供操作的服务描述体现为如下一个ServiceDescriptor类型。
public class ServiceDescriptor
{
public ServiceDescriptor(Type serviceType, object instance);
public ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetimelifetime);
public ServiceDescriptor(Type serviceType, TypeimplementationType, ServiceLifetime lifetime);
public Type ServiceType { get; }
public ServiceLifetime Lifetime { get; }
public Type ImplementationType { get; }
public object ImplementationInstance { get; }
public Func<IServiceProvider, object> ImplementationFactory{ get; }
}
ASP.NET Core中的ServiceProvider是根据一个代表ServiceDescriptor集合的IServiceCollection对象创建的,当我们调用其GetService方法的时候,它会根据我们提供的服务类型找到对应的ServiceDecriptor对象。如果该ServiceDecriptor对象的ImplementationInstance属性返回一个具体的对象,该对象将直接用作被提供的服务实例
所以要移除某个服务找到其在ServiceCollection中注册的对应ServiceDesriptor就可以
public static IServiceCollection RemoveRegisteredServiceExtension(this IServiceCollection services)
{
var descriptorDbContext = services.FirstOrDefault(descriptor => descriptor.Name == nameof(RemoveService));
services.Remove(descriptorDbContext);
return services;
}