Faster RequestServices (#941)

* Faster RequestServices
This commit is contained in:
Ben Adams 2017-02-14 16:37:38 +00:00 committed by David Fowler
parent 1b01da7a05
commit 2697ad9a37
2 changed files with 22 additions and 24 deletions

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
public class RequestServicesContainerMiddleware public class RequestServicesContainerMiddleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
public RequestServicesContainerMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory) public RequestServicesContainerMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory)
{ {
@ -25,37 +26,37 @@ namespace Microsoft.AspNetCore.Hosting.Internal
throw new ArgumentNullException(nameof(scopeFactory)); throw new ArgumentNullException(nameof(scopeFactory));
} }
_scopeFactory = scopeFactory;
_next = next; _next = next;
_scopeFactory = scopeFactory;
} }
public async Task Invoke(HttpContext httpContext) public async Task Invoke(HttpContext httpContext)
{ {
if (httpContext == null) Debug.Assert(httpContext != null);
{
throw new ArgumentNullException(nameof(httpContext));
}
var existingFeature = httpContext.Features.Get<IServiceProvidersFeature>(); // local cache for virtual disptach result
var features = httpContext.Features;
var existingFeature = features.Get<IServiceProvidersFeature>();
// All done if request services is set // All done if RequestServices is set
if (existingFeature?.RequestServices != null) if (existingFeature?.RequestServices != null)
{ {
await _next.Invoke(httpContext); await _next.Invoke(httpContext);
return; return;
} }
using (var feature = new RequestServicesFeature(_scopeFactory)) var replacementFeature = new RequestServicesFeature(_scopeFactory);
try
{ {
try features.Set<IServiceProvidersFeature>(replacementFeature);
{ await _next.Invoke(httpContext);
httpContext.Features.Set<IServiceProvidersFeature>(feature); }
await _next.Invoke(httpContext); finally
} {
finally replacementFeature.Dispose();
{ // Restore previous feature state
httpContext.Features.Set(existingFeature); features.Set(existingFeature);
}
} }
} }
} }

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -9,18 +10,14 @@ namespace Microsoft.AspNetCore.Hosting.Internal
{ {
public class RequestServicesFeature : IServiceProvidersFeature, IDisposable public class RequestServicesFeature : IServiceProvidersFeature, IDisposable
{ {
private IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
private IServiceProvider _requestServices; private IServiceProvider _requestServices;
private IServiceScope _scope; private IServiceScope _scope;
private bool _requestServicesSet; private bool _requestServicesSet;
public RequestServicesFeature(IServiceScopeFactory scopeFactory) public RequestServicesFeature(IServiceScopeFactory scopeFactory)
{ {
if (scopeFactory == null) Debug.Assert(scopeFactory != null);
{
throw new ArgumentNullException(nameof(scopeFactory));
}
_scopeFactory = scopeFactory; _scopeFactory = scopeFactory;
} }