ServiceProvider.GetRequiredService против ApplicationServies.GetRequiredService с одиночной службой - PullRequest
0 голосов
/ 28 августа 2018

Какая разница в звонках на синглтон-сервис?

В приложении. ИспользованиеMvc ();

app.UseMvc(options =>
{
    options
        .ServiceProvider
        .GetRequiredService<IYamlIndexer>()
        .IndexContentFiles(Constants.ContentPath);
});

Или это:

app
    .ApplicationServices
    .GetRequiredService<IYamlIndexer>()
    .IndexContentFiles(Constants.ContentPath);

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Короткий ответ

В большинстве случаев нет разницы между ними. Оба свойства указывают на один и тот же экземпляр IServiceProvider, и оба получат один и тот же экземпляр требуемой одноэлементной службы. В крайних случаях время вызовов может быть другим, но я не мог придумать крайний случай, который мог бы вызвать это. Если мы не делаем что-то необычное, оба будут работать только один раз, и это будет во время запуска приложения.

Эксперимент для демонстрации

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSingleton<SomeSingltonService>();
    }

    public void Configure(IApplicationBuilder app)
    {
        var appServices = app.ApplicationServices;
        var appService = appServices.GetRequiredService<SomeSingltonService>();

        Console.WriteLine("=======================");
        Console.WriteLine("Configure");

        app.UseMvc(configureRoutes =>
        {
            var routeServices = routeBuilder.ServiceProvider;
            var routeService = routeServices.GetRequiredService<SomeSingltonService>();

            Console.WriteLine("UseMvc");

            if (appServices == routeServices && appService == routeService)
            {
                Console.WriteLine("They are the same instances.");
            }
        });

        Console.WriteLine("=======================");
    }
}

Это вывод:

=======================        
Configure                      
UseMvc                         
They are the same instance.    
=======================        

Исходный код для демонстрации

За кулисами UseMvc передает IApplicationBulder в конструктор RouteBuilder. Затем RouteBuilder назначает IApplicationBulder.ApplicationServices собственному свойству IRouteBuilder.ServiceProvider.

Код от MvcApplicationBuilderExtensions.cs

public static IApplicationBuilder UseMvc(
    this IApplicationBuilder app,
    Action<IRouteBuilder> configureRoutes)
{
    // ...

    var routes = new RouteBuilder(app) // ln 136
    {
        DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
    };

    configureRoutes(routes);

    // ...
}

Код от RouteBuilder.cs

public RouteBuilder(IApplicationBuilder applicationBuilder, IRouter defaultHandler)
{
    // ...

    ServiceProvider = applicationBuilder.ApplicationServices; // ln 36

    // ...
}
0 голосов
/ 28 августа 2018

In (2) IndexContentFiles запустится немедленно, во время запуска приложения, пока приложение не «полностью запущено». Это может вызвать некоторые проблемы (в зависимости от того, что на самом деле делает IYamlIndexer.IndexContentFiles). Кроме того, если это синхронный длительный вызов - ваше приложение будет работать медленно при запуске.

В (1) этот метод запустится .. когда подсистема MVC запросит опции. Это произойдет где-то после запуска приложения и снова займет некоторое время, если оно долго работает ...

И вопрос, который вы должны задать себе - как настраиваются параметры - одиночный или временный (и почему вы доверяете этим знаниям)? В худшем случае ваш IndexContentFiles будет вызываться каждый раз, когда запрашиваются параметры MVC, и ваше приложение умирает, вызывая IndexContentFiles при каждом запросе пользователя ...

Может быть, вам нужно что-то вроде IApplicationLifetime ?

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