Reputation: 203
What's the difference in calling singleton service.
In app.UseMvc();
app.UseMvc(options =>
{
options
.ServiceProvider
.GetRequiredService<IYamlIndexer>()
.IndexContentFiles(Constants.ContentPath);
});
Or this:
app
.ApplicationServices
.GetRequiredService<IYamlIndexer>()
.IndexContentFiles(Constants.ContentPath);
Upvotes: 4
Views: 3686
Reputation: 141512
For most use cases, there is not a difference between the two. Both properties point to the same IServiceProvider
instance, and both will get the same instance of a required singleton service. In edge cases, the timing of the calls might be different, but I could not think of an edge case that would cause that to happen. Unless we're doing something unusual, both will run only once, and that will be during application startup.
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("=======================");
}
}
This is the output:
=======================
Configure
UseMvc
They are the same instance.
=======================
Behind the scenes UseMvc
passes the IApplicationBulder
to the RouteBuilder
constructor. Then the RouteBuilder
assigns the IApplicationBulder.ApplicationServices
to its own IRouteBuilder.ServiceProvider
property.
Code from 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);
// ...
}
Code from RouteBuilder.cs
public RouteBuilder(IApplicationBuilder applicationBuilder, IRouter defaultHandler)
{
// ...
ServiceProvider = applicationBuilder.ApplicationServices; // ln 36
// ...
}
Upvotes: 1
Reputation: 16795
In (2) IndexContentFiles
will start immediately, during app startup, while application is not "fully running". This may cause some problems (depending of what IYamlIndexer.IndexContentFiles actually doing). Also, if this is synchronous long-running call - your app will be slow during startup.
In (1) this method will start.. at some time where MVC subsystem will ask for it options. This will occur somewhere after app startup, and again will take some time if it's long-running...
And question you should ask yourself - how Options are configured - singleton or transient (and why you trust this knowlege)? In worst case, your IndexContentFiles
will be called each time MVC Options are requested and your app will die calling IndexContentFiles on every user request...
May be you need something like IApplicationLifetime?
Upvotes: 0