替换ASP.NET Core内置DI容器中的服务注册?
让我们考虑一下Startup.ConfigureServices
的服务注册:
public void ConfigureServices(IServiceCollection services) { services.AddTransient(); }
调用FooB
后,是否可以将IFoo
注册更改为FooB
? 它有助于测试目的(例如,在TestStartup
子类中)或者我们对代码库的访问是有限的。
如果我们注册另一个IFoo
实现:
services.AddTransient(); services.AddTransient();
然后GetService
返回FooB
而不是FooA
:
IFoo service = services.BuildServiceProvider().GetService(); Assert.True(service is FooB);
但是, GetServices
成功返回两个实现(对于GetService<IEnumerable>
):
var list = services.BuildServiceProvider().GetServices().ToList(); Assert.Equal(2, list.Count);
IServiceCollection
合同中有Remove(ServiceDescriptor)
方法。 我应该如何使用ServiceDescriptor
来修改服务注册?
使用ServiceCollectionDescriptorExtensions
类中的Replace(IServiceCollection, ServiceDescriptor)
方法很简单。
// IFoo -> FooA services.AddTransient(); // Replace // IFoo -> FooB var descriptor = new ServiceDescriptor( typeof(IFoo), typeof(FooB), ServiceLifetime.Transient); services.Replace(descriptor);
也可以看看:
- ServiceDescriptor构造函数
如果你知道两件简单的事情,很容易覆盖ASP.NET Core DIfunction:
1. ServiceCollection
只是List
之上的包装器:
public class ServiceCollection : IServiceCollection { private List _descriptors = new List (); }
2.注册服务时,会在列表中添加新的描述符:
private static IServiceCollection Add( IServiceCollection collection, Type serviceType, Type implementationType, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime); collection.Add(descriptor); return collection; }
因此,可以在此列表中添加/删除描述符以替换注册:
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);
我们用Replace
方法完成:
services.Replace(ServiceLifetime.Transient);
它的实施:
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; }
- 使用Postman上传ASP核心WebApi测试文件
- 从.NET Core / ASP.NET Core中的类库访问App密钥数据
- AWS中托管的.NET Core 2 Web应用程序中的计划作业
- Windows 10上的.net核心安装iot(Raspberry PI3 – ARM)
- 如何在Visual Studio中测量ASP.NET Core项目中的代码覆盖率?
- net462应用程序引用netstandard1.5库时出现“无法加载文件或程序集”错误。 但为什么?
- 为什么我的PCL不能使用System.Runtime?
- 是否可以使用.net core Roslyn编译器编译单个C#代码文件?
- ASP.NET Core 2 – 身份 – 自定义角色的DI错误