asp.Netcore 3.1ソース学習のいくつかのコアのオブジェクト
34920 ワード
一、IApplicationBuilderFactory
二、IApplicationBuilder
ApplicationBuilderのフィールド_components保存asp.Netcoreの処理パイプは、Use(Func middleware)メソッドを呼び出すと、リストに登録されます.
Build()メソッドは、aspであるRequestDelegateを構築する.Netcoreパイプ処理要求と応答のコア
三、IHttpContextFactory
四、IHttpApplication
IHttpApplicationはリクエストと見なすことができます
CreateContext Contextオブジェクトの作成
ProcessRequestAsyncメソッドは最終的に上のRequestDelegateを呼び出し、aspに進む.Netcoreのパイプでの要求と応答の処理
public interface IApplicationBuilderFactory
{
IApplicationBuilder CreateBuilder(IFeatureCollection serverFeatures);
}
public class ApplicationBuilderFactory : IApplicationBuilderFactory
{
private readonly IServiceProvider _serviceProvider;
public ApplicationBuilderFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IApplicationBuilder CreateBuilder(IFeatureCollection serverFeatures)
{
return new ApplicationBuilder(_serviceProvider, serverFeatures);
}
}
二、IApplicationBuilder
public interface IApplicationBuilder { ///
/// Gets or sets the
that provides access to the application's service container. /// IServiceProvider ApplicationServices { get; set; } /// /// Gets the set of HTTP features the application's server provides. /// IFeatureCollection ServerFeatures { get; } ///
/// Gets a key/value collection that can be used to share data between middleware. /// IDictionary<string, object> Properties { get; } ///
/// Adds a middleware delegate to the application's request pipeline. /// /// The middleware delegate. ///
The . IApplicationBuilder Use(Func middleware); /// /// Creates a new
that shares the of this /// . /// /// The new . IApplicationBuilder New(); /// /// Builds the delegate used by this application to process HTTP requests. /// ///
The request handling delegate. RequestDelegate Build(); }
public class ApplicationBuilder : IApplicationBuilder
{
private const string ServerFeaturesKey = "server.Features";
private const string ApplicationServicesKey = "application.Services";
private readonly IList> _components = new List>();
public ApplicationBuilder(IServiceProvider serviceProvider)
{
Properties = new Dictionary<string, object>(StringComparer.Ordinal);
ApplicationServices = serviceProvider;
}
public ApplicationBuilder(IServiceProvider serviceProvider, object server)
: this(serviceProvider)
{
SetProperty(ServerFeaturesKey, server);
}
private ApplicationBuilder(ApplicationBuilder builder)
{
Properties = new CopyOnWriteDictionary<string, object>(builder.Properties, StringComparer.Ordinal);
}
public IServiceProvider ApplicationServices
{
get
{
return GetProperty(ApplicationServicesKey);
}
set
{
SetProperty(ApplicationServicesKey, value);
}
}
public IFeatureCollection ServerFeatures
{
get
{
return GetProperty(ServerFeaturesKey);
}
}
public IDictionary<string, object> Properties { get; }
private T GetProperty(string key)
{
object value;
return Properties.TryGetValue(key, out value) ? (T)value : default(T);
}
private void SetProperty(string key, T value)
{
Properties[key] = value;
}
public IApplicationBuilder Use(Func middleware)
{
_components.Add(middleware);
return this;
}
public IApplicationBuilder New()
{
return new ApplicationBuilder(this);
}
public RequestDelegate Build()
{
RequestDelegate app = context =>
{
// If we reach the end of the pipeline, but we have an endpoint, then something unexpected has happened.
// This could happen if user code sets an endpoint, but they forgot to add the UseEndpoint middleware.
var endpoint = context.GetEndpoint();
var endpointRequestDelegate = endpoint?.RequestDelegate;
if (endpointRequestDelegate != null)
{
var message =
$"The request reached the end of the pipeline without executing the endpoint: '{endpoint.DisplayName}'. " +
$"Please register the EndpointMiddleware using '{nameof(IApplicationBuilder)}.UseEndpoints(...)' if using " +
$"routing.";
throw new InvalidOperationException(message);
}
context.Response.StatusCode = 404;
return Task.CompletedTask;
};
foreach (var component in _components.Reverse())
{
app = component(app);
}
return app;
}
}
ApplicationBuilderのフィールド_components保存asp.Netcoreの処理パイプは、Use(Func middleware)メソッドを呼び出すと、リストに登録されます.
Build()メソッドは、aspであるRequestDelegateを構築する.Netcoreパイプ処理要求と応答のコア
三、IHttpContextFactory
public interface IHttpContextFactory
{
HttpContext Create(IFeatureCollection featureCollection);
void Dispose(HttpContext httpContext);
}
public class DefaultHttpContextFactory : IHttpContextFactory
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly FormOptions _formOptions;
private readonly IServiceScopeFactory _serviceScopeFactory;
// This takes the IServiceProvider because it needs to support an ever expanding
// set of services that flow down into HttpContext features
public DefaultHttpContextFactory(IServiceProvider serviceProvider)
{
// May be null
_httpContextAccessor = serviceProvider.GetService();
_formOptions = serviceProvider.GetRequiredService>().Value;
_serviceScopeFactory = serviceProvider.GetRequiredService();
}
public HttpContext Create(IFeatureCollection featureCollection)
{
if (featureCollection is null)
{
throw new ArgumentNullException(nameof(featureCollection));
}
var httpContext = new DefaultHttpContext(featureCollection);
Initialize(httpContext);
return httpContext;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Initialize(DefaultHttpContext httpContext, IFeatureCollection featureCollection)
{
Debug.Assert(featureCollection != null);
Debug.Assert(httpContext != null);
httpContext.Initialize(featureCollection);
Initialize(httpContext);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private DefaultHttpContext Initialize(DefaultHttpContext httpContext)
{
if (_httpContextAccessor != null)
{
_httpContextAccessor.HttpContext = httpContext;
}
httpContext.FormOptions = _formOptions;
httpContext.ServiceScopeFactory = _serviceScopeFactory;
return httpContext;
}
public void Dispose(HttpContext httpContext)
{
if (_httpContextAccessor != null)
{
_httpContextAccessor.HttpContext = null;
}
}
internal void Dispose(DefaultHttpContext httpContext)
{
if (_httpContextAccessor != null)
{
_httpContextAccessor.HttpContext = null;
}
httpContext.Uninitialize();
}
}
四、IHttpApplication
///
/// Represents an application. /// ///
The context associated with the application. public interface IHttpApplication { /// /// Create a TContext given a collection of HTTP features. /// /// A collection of HTTP features to be used for creating the TContext. ///
The created TContext. TContext CreateContext(IFeatureCollection contextFeatures); /// /// Asynchronously processes an TContext. /// /// The TContext that the operation will process. Task ProcessRequestAsync(TContext context); ///
/// Dispose a given TContext. /// /// The TContext to be disposed. /// The Exception thrown when processing did not complete successfully, otherwise null. void DisposeContext(TContext context, Exception exception); }
internal class HostingApplication : IHttpApplication
{
private readonly RequestDelegate _application;
private readonly IHttpContextFactory _httpContextFactory;
private readonly DefaultHttpContextFactory _defaultHttpContextFactory;
private HostingApplicationDiagnostics _diagnostics;
public HostingApplication(
RequestDelegate application,
ILogger logger,
DiagnosticListener diagnosticSource,
IHttpContextFactory httpContextFactory)
{
_application = application;
_diagnostics = new HostingApplicationDiagnostics(logger, diagnosticSource);
if (httpContextFactory is DefaultHttpContextFactory factory)
{
_defaultHttpContextFactory = factory;
}
else
{
_httpContextFactory = httpContextFactory;
}
}
// Set up the request
public Context CreateContext(IFeatureCollection contextFeatures)
{
Context hostContext;
if (contextFeatures is IHostContextContainer container)
{
hostContext = container.HostContext;
if (hostContext is null)
{
hostContext = new Context();
container.HostContext = hostContext;
}
}
else
{
// Server doesn't support pooling, so create a new Context
hostContext = new Context();
}
HttpContext httpContext;
if (_defaultHttpContextFactory != null)
{
var defaultHttpContext = (DefaultHttpContext)hostContext.HttpContext;
if (defaultHttpContext is null)
{
httpContext = _defaultHttpContextFactory.Create(contextFeatures);
hostContext.HttpContext = httpContext;
}
else
{
_defaultHttpContextFactory.Initialize(defaultHttpContext, contextFeatures);
httpContext = defaultHttpContext;
}
}
else
{
httpContext = _httpContextFactory.Create(contextFeatures);
hostContext.HttpContext = httpContext;
}
_diagnostics.BeginRequest(httpContext, hostContext);
return hostContext;
}
// Execute the request
public Task ProcessRequestAsync(Context context)
{
return _application(context.HttpContext);
}
// Clean up the request
public void DisposeContext(Context context, Exception exception)
{
var httpContext = context.HttpContext;
_diagnostics.RequestEnd(httpContext, exception, context);
if (_defaultHttpContextFactory != null)
{
_defaultHttpContextFactory.Dispose((DefaultHttpContext)httpContext);
}
else
{
_httpContextFactory.Dispose(httpContext);
}
_diagnostics.ContextDisposed(context);
// Reset the context as it may be pooled
context.Reset();
}
internal class Context
{
public HttpContext HttpContext { get; set; }
public IDisposable Scope { get; set; }
public Activity Activity { get; set; }
public long StartTimestamp { get; set; }
internal bool HasDiagnosticListener { get; set; }
public bool EventLogEnabled { get; set; }
public void Reset()
{
// Not resetting HttpContext here as we pool it on the Context
Scope = null;
Activity = null;
StartTimestamp = 0;
HasDiagnosticListener = false;
EventLogEnabled = false;
}
}
}
IHttpApplicationはリクエストと見なすことができます
CreateContext Contextオブジェクトの作成
internal class Context
{
public HttpContext HttpContext { get; set; }
public IDisposable Scope { get; set; }
public Activity Activity { get; set; }
public long StartTimestamp { get; set; }
internal bool HasDiagnosticListener { get; set; }
public bool EventLogEnabled { get; set; }
public void Reset()
{
// Not resetting HttpContext here as we pool it on the Context
Scope = null;
Activity = null;
StartTimestamp = 0;
HasDiagnosticListener = false;
EventLogEnabled = false;
}
}
ProcessRequestAsyncメソッドは最終的に上のRequestDelegateを呼び出し、aspに進む.Netcoreのパイプでの要求と応答の処理