首页 > 解决方案 > .Net Core Dependency injection services.Add vs services.Replace

问题描述

例如,使用 services.(AddScoped, AddTransient, AddSingleton) 和 service.replace 注入服务有什么区别

services.AddScoped<IPasswordHasher<ApplicationUser>, SqlPasswordHasher<ApplicationUser>>();
services.Replace(new ServiceDescriptor(
    serviceType: typeof(IPasswordHasher<ApplicationUser>),
    implementationType: typeof(SqlPasswordHasher<ApplicationUser>),
        ServiceLifetime.Scoped));

标签: c#.net-coredependency-injectionasp.net-identityasp.net-core-identity

解决方案


可以在源代码中看到差异。

第一个是IServiceCollection接口,是依赖注入的核心接口。

public interface IServiceCollection : IList<ServiceDescriptor>
{
}

IServiceCollection只是一个ServiceDescriptor对象列表。ServiceDescriptor描述注入类型的信息。

基于这个接口,可以对这两种方法Add进行Replace讨论。

public static IServiceCollection Add(
            this IServiceCollection collection,
            ServiceDescriptor descriptor)
{
    ...
    collection.Add(descriptor);
    return collection;
}

public static IServiceCollection Replace(
            this IServiceCollection collection,
            ServiceDescriptor descriptor)
{
    ...
    // Remove existing
    int count = collection.Count;
    for (int i = 0; i < count; i++)
    {
        if (collection[i].ServiceType == descriptor.ServiceType)
        {
            collection.RemoveAt(i);
            break;
        }
    }
    collection.Add(descriptor);
    return collection;
}

Add只是将服务描述符推送到列表中,同时Replace首先检查并删除列表中具有相同服务类型的描述符,最后将当前描述符添加到列表中。

因此,这两种方法的时间复杂度是不同的。大多数情况下的时间复杂度Add是O(1),Replace而是O(n)(遍历列表)。但是,Add不保证添加的描述符是唯一的,而是Replace会删除具有相同服务类型的描述符并添加当前的描述符。


推荐阅读