首页 > 解决方案 > ServiceProvider.GetRequiredService 与 ApplicationServies.GetRequiredService 与单例服务

问题描述

调用单例服务有什么区别。

在 app.UseMvc();

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

或这个:

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

标签: asp.net-core.net-core

解决方案


简答

对于大多数用例,两者之间没有区别。两个属性都指向同一个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将 传递IApplicationBulderRouteBuilder构造函数。然后将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

    // ...
}

推荐阅读