Вопрос о шаблоне C# в ядре ASP. NET при добавлении служб в Startup.cs - PullRequest
1 голос
/ 08 мая 2020

Что касается этого кода для настройки служб:

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

и, в частности, строки:

services.AddSingleton<IDb, Db>();

будет ли какая-либо разница c, если AddSingleton вместо того, чтобы быть обобщенная функция c с 0 параметрами, как в фрагменте кода, вместо этого была

AddSingleton(Type type1, Type type2);

Ответы [ 3 ]

3 голосов
/ 08 мая 2020

Реализация 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)). Оба вызова приведут к одному и тому же результату.

Причина общей c перегрузки в том, что она кажется намного лучше. Методы Generi c предпочтительнее передаваемых типов, потому что вы можете просто написать их проще. Таким образом, вы с большей вероятностью увидите использование generi c.

Кроме того, есть преимущество, заключающееся в том, что вы можете добавлять ограничения к аргументам типа generi c, которые могут добавлять некоторые проверки времени компиляции. В данном конкретном случае ограничения выглядят следующим образом:

where TService : class
where TImplementation : class, TService

Помимо того, что оба типа должны быть ссылочными типами, существует дополнительное требование, которое TImplementation наследует от TService. Это гарантирует, что вы действительно можете использовать экземпляры типа TImplementation в местах, где ожидается TService. Это также идея принципа замены Лискова . При наличии ограничения типа эта проверка проверяется во время компиляции , поэтому вы можете быть уверены, что это будет работать во время выполнения, поскольку это не гарантируется, если вы используете другую перегрузку.

Излишне говорить, что AddTransient<> и AddScoped<> работают одинаково с соответствующими не-родовыми c перегрузками.

2 голосов
/ 08 мая 2020

Семантически оба означают одно и то же. Однако одним из преимуществ использования метода generi c является то, что ограничения на типы, передаваемые в вызов метода, могут быть применены во время компиляции.

В документации для этого метода обратите внимание на ограничение where TImplementation : class, TService. Компилятор может проверить во время компиляции, что тип Db реализует IDb и является классом.

При использовании не-generi c метода это невозможно во время компиляции. (Вместо этого его можно проверить во время выполнения, и может возникнуть ошибка выполнения.)

1 голос
/ 08 мая 2020

Если вы выполните поиск в документации Microsoft, вы обнаружите, что все Addsingleton работают одинаково, единственное, что отличается, - это запись:

AddSingleton : добавляет одноэлементную службу тип, указанный в TService, с типом реализации, указанным в TImplementation, в указанную IServiceCollection.

AddSingleton (IServiceCollection, Type, Type): Добавляет одноэлементную службу типа, указанного в serviceType, с реализация типа, указанного в implementationType, в указанную коллекцию IServiceCollection.

источник документации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...