繁体   English   中英

关于 Startup.cs 添加服务时 ASP.NET Core 中 C# 模式的问题

[英]Question about C# Pattern in ASP.NET Core When Adding Services in Startup.cs

关于此代码来配置服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDb, Db>();
    services.AddControllers();
}

特别是这一行:

services.AddSingleton<IDb, Db>();

如果 AddSingleton 不是像代码片段中那样是具有 0 个参数的通用 function ,是否会有任何语义差异

AddSingleton(Type type1, Type type2);

AddSingleton<T1, T2>的实现如下所示:

public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services)
    where TService : class
    where TImplementation : class, TService
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }

    return services.AddSingleton(typeof(TService), typeof(TImplementation));
}

如您所见,它实际上调用了传递两种类型的AddSingleton的另一个重载。 因此,从语义上讲,无论您执行AddSingleton<IDb, Db>()还是AddSingleton(typeof(IDb), typeof(Db))都没有区别。 两次调用都将产生完全相同的结果。

有一个通用重载的原因是它感觉好多了。 泛型方法优于传递类型,因为您可以更轻松地编写它。 因此,您更有可能看到通用用法。

此外,您可以向泛型类型 arguments 添加约束,这可能会增加一些编译时检查。 在这种特殊情况下,约束如下所示:

where TService : class
where TImplementation : class, TService

除了这两种类型都必须是引用类型之外,还有一个额外的要求,即TImplementation继承自TService 这确保您可以在需要TImplementation的地方实际使用TService类型的实例。 这也是里氏替换原则背后的理念。 通过具有类型约束,此检查将在编译时进行验证,因此您可以确保这将在运行时工作,因为如果您使用其他重载则无法保证这一点。

不用说, AddTransient<>AddScoped<>在它们各自的非泛型重载上的工作方式相同。

从语义上讲,两者的含义相同。 但是,使用泛型方法的一个优点是可以在编译时强制对传递给方法调用的类型进行约束。

此方法的文档中,请注意约束, where TImplementation: class, TService 编译器可以在编译时检查Db类型是否实现了IDb并且是 class。

使用非泛型方法,这在编译时是不可能的。 (相反,它可以在运行时检查,并且可能会引发运行时错误。)

如果你搜索微软的文档,你会发现所有 Addsingleton 的工作方式都是一样的,唯一不同的是条目:

AddSingleton :将 TService 中指定的类型的 singleton 服务与 TImplementation 中指定的实现类型添加到指定的 IServiceCollection。

AddSingleton(IServiceCollection, Type, Type):将 serviceType 中指定类型的 singleton 服务与 implementationType 中指定的类型的实现添加到指定的 IServiceCollection。

文档来源

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM