【问题标题】:Remove a service in ASP.Net Core Dependency Injection [duplicate]在 ASP.Net Core Dependency Injection 中删除服务 [重复]
【发布时间】:2017-08-14 05:24:49
【问题描述】:

在 Asp.Net MVC Core(早期版本,版本 1.0 或 1.1)中,依赖注入绑定在 Startup.cs 类中配置如下:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyService, MyService>();
        // ...
    }
}

在我的应用程序中,我通常有一个基 Startup 类,其中泛型绑定被定义为这些行的序列:

public abstract class BaseStartup
{
    public virtual void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyService1, MyService1>();
        services.AddScoped<IMyService2, MyService2>();
    }
}

然后在我的应用程序中,我继承启动类,并注入其他服务:

public class Startup : BaseStartup
{
    public override void ConfigureServices(IServiceCollection services)
    {
        base.ConfigureServices(services);

        services.AddScoped<IMyService3, MyService3>();
        services.AddScoped<IMyService4, MyService4>();
    }
}

我现在想知道:我怎样才能“覆盖”以前的绑定? 例如,我想删除或修改基类中定义的绑定,例如:

services.Remove<IMyService1>(); // Doesn't exist
services.AddScoped<IMyService1, MyBetterService1>();

或者只是更新绑定:

services.AddScoped<IMyService1, MyBetterService1>(replacePreviousBinding: true); // Doesn't exist either !

有没有办法做到这一点?或者简单地声明一个与先前定义的绑定具有相同接口的新绑定将覆盖该绑定?

【问题讨论】:

    标签: c# asp.net-mvc dependency-injection asp.net-core-mvc


    【解决方案1】:

    您可以使用普通的收集 API 来删除您的服务:

    services.AddScoped<IService>();
    
    var serviceDescriptor = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IService));
    services.Remove(serviceDescriptor);
    

    您也可以创建扩展方法来实现相同的目的:

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection Remove<T>(this IServiceCollection services)
        {
            if (services.IsReadOnly)
            {
                throw new ReadOnlyException($"{nameof(services)} is read only");
            }
    
            var serviceDescriptor = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(T));
            if (serviceDescriptor != null) services.Remove(serviceDescriptor);
    
            return services;
        }
    }
    

    【讨论】:

    • 这听起来很完美,正是我所需要的。当我想到这种方法时,我不知道应该使用什么“密钥”,然后 serviceDescriptor 就是答案。我想知道为什么他们没有在框架内提供扩展。一旦我测试过,我会给你投票并将答案标记为已接受。
    • 超级,我在发布答案之前已经在本地进行了测试,所以我希望它可以工作。也许他们不认为添加这些额外的方法是一种常见的情况。
    • 好的,如果你测试过,我现在接受答案。由于我需要在一项大型重构任务中使用它,因此我距离准备好测试我的代码太远了!!
    • 我已编辑您的答案以尊重这些扩展中使用的 Fluent API 样式,以便可以进行链式调用。
    • 一个轻微的 mod 建议来检查集合是否是只读的(在 .Build() 之后) if (services.IsReadOnly) { throw new ReadOnlyException($"{nameof(services)} 是只读的"); }
    猜你喜欢
    • 2021-08-03
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多