首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >替换ASP.NET核心内置DI容器中的服务注册?

替换ASP.NET核心内置DI容器中的服务注册?
EN

Stack Overflow用户
提问于 2017-04-24 22:26:21
回答 3查看 39.4K关注 0票数 79

让我们考虑一下Startup.ConfigureServices

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient();
}

有没有可能改变IFoo注册到FooB之后AddTransient已经被调用了吗?它对测试目的很有帮助(例如,在TestStartup子类),或者我们对代码库的访问受到限制。如果我们注册另一个IFoo实施:

代码语言:javascript
复制
services.AddTransient();
services.AddTransient();

然后GetService返回FooB而不是FooA

代码语言:javascript
复制
IFoo service = services.BuildServiceProvider().GetService();
Assert.True(service is FooB);

然而,GetServices成功返回两个实现(对于GetService>):

代码语言:javascript
复制
var list = services.BuildServiceProvider().GetServices().ToList();
Assert.Equal(2, list.Count);

Remove(ServiceDescriptor)中的方法IServiceCollection合同。我该怎么做?ServiceDescriptor修改服务注册?

EN

回答 3

Stack Overflow用户

发布于 2017-04-24 22:40:27

这很简单,使用替换Replace(IServiceCollection, ServiceDescriptor)方法,该方法来自ServiceCollectionDescriptorExtensions类。

代码语言:javascript
复制
// IFoo -> FooA
services.AddTransient();

// Replace
// IFoo -> FooB
var descriptor =
    new ServiceDescriptor(
        typeof(IFoo),
        typeof(FooB),
        ServiceLifetime.Transient);
services.Replace(descriptor);

另请参阅:

票数 109
EN

Stack Overflow用户

发布于 2017-04-24 22:26:35

如果您知道两件简单的事情,那么覆盖ASP.NET核心DI功能是很容易的:

1.ServiceCollection只是一个包装器,放在List:

代码语言:javascript
复制
public class ServiceCollection : IServiceCollection
    {
        private List _descriptors = new List();
    }

2.注册服务时,新的描述符是添加到list

代码语言:javascript
复制
private static IServiceCollection Add(
        IServiceCollection collection,
        Type serviceType,
        Type implementationType,
        ServiceLifetime lifetime)
    {
        var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
        collection.Add(descriptor);
        return collection;
    }

因此,可以在此列表中添加/删除描述符,以替换注册:

代码语言:javascript
复制
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扩展方法:

代码语言:js
复制
services.Replace(ServiceLifetime.Transient);

它的实现:

代码语言:javascript
复制
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;
}
票数 48
EN

Stack Overflow用户

发布于 2020-05-10 03:04:40

在@ilya-chumakov的很好的答案上补充一下,这里是相同的方法,但支持实现工厂

代码语言:javascript
复制
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;
}

以防我们想要将其与实例化服务的工厂一起使用,如以下示例所示:

代码语言:javascript
复制
var serviceProvider = 
  new ServiceCollection()
    .Replace(sp => new MyService(), ServiceLifetime.Singleton)
    .BuildServiceProvider();
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43590769

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档