让我们考虑一下Startup.ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient();
}
有没有可能改变IFoo
注册到FooB
之后AddTransient
已经被调用了吗?它对测试目的很有帮助(例如,在TestStartup
子类),或者我们对代码库的访问受到限制。如果我们注册另一个IFoo
实施:
services.AddTransient();
services.AddTransient();
然后GetService
返回FooB
而不是FooA
IFoo service = services.BuildServiceProvider().GetService();
Assert.True(service is FooB);
然而,GetServices
成功返回两个实现(对于GetService>
):
var list = services.BuildServiceProvider().GetServices().ToList();
Assert.Equal(2, list.Count);
有Remove(ServiceDescriptor)
中的方法IServiceCollection
合同。我该怎么做?ServiceDescriptor
修改服务注册?
发布于 2017-04-24 22:40:27
这很简单,使用替换Replace(IServiceCollection, ServiceDescriptor)
方法,该方法来自ServiceCollectionDescriptorExtensions
类。
// IFoo -> FooA
services.AddTransient();
// Replace
// IFoo -> FooB
var descriptor =
new ServiceDescriptor(
typeof(IFoo),
typeof(FooB),
ServiceLifetime.Transient);
services.Replace(descriptor);
另请参阅:
发布于 2017-04-24 22:26:35
如果您知道两件简单的事情,那么覆盖ASP.NET核心DI功能是很容易的:
1.ServiceCollection
只是一个包装器,放在List
:
public class ServiceCollection : IServiceCollection
{
private List _descriptors = new List();
}
2.注册服务时,新的描述符是添加到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;
}
因此,可以在此列表中添加/删除描述符,以替换注册:
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;
}
发布于 2020-05-10 03:04:40
在@ilya-chumakov的很好的答案上补充一下,这里是相同的方法,但支持实现工厂
public static IServiceCollection Replace(
this IServiceCollection services,
Func 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;
}
以防我们想要将其与实例化服务的工厂一起使用,如以下示例所示:
var serviceProvider =
new ServiceCollection()
.Replace(sp => new MyService(), ServiceLifetime.Singleton)
.BuildServiceProvider();
https://stackoverflow.com/questions/43590769
复制相似问题