• asp.net core 3.1 源码学习之几个核心的对象


    一、IApplicationBuilderFactory

    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
        {
            /// <summary>
            /// Gets or sets the <see cref="IServiceProvider"/> that provides access to the application's service container.
            /// </summary>
            IServiceProvider ApplicationServices { get; set; }
    
            /// <summary>
            /// Gets the set of HTTP features the application's server provides.
            /// </summary>
            IFeatureCollection ServerFeatures { get; }
    
            /// <summary>
            /// Gets a key/value collection that can be used to share data between middleware.
            /// </summary>
            IDictionary<string, object> Properties { get; }
    
            /// <summary>
            /// Adds a middleware delegate to the application's request pipeline.
            /// </summary>
            /// <param name="middleware">The middleware delegate.</param>
            /// <returns>The <see cref="IApplicationBuilder"/>.</returns>
            IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
    
            /// <summary>
            /// Creates a new <see cref="IApplicationBuilder"/> that shares the <see cref="Properties"/> of this
            /// <see cref="IApplicationBuilder"/>.
            /// </summary>
            /// <returns>The new <see cref="IApplicationBuilder"/>.</returns>
            IApplicationBuilder New();
    
            /// <summary>
            /// Builds the delegate used by this application to process HTTP requests.
            /// </summary>
            /// <returns>The request handling delegate.</returns>
            RequestDelegate Build();
        }
    public class ApplicationBuilder : IApplicationBuilder
        {
            private const string ServerFeaturesKey = "server.Features";
            private const string ApplicationServicesKey = "application.Services";
    
            private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();
    
            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<IServiceProvider>(ApplicationServicesKey);
                }
                set
                {
                    SetProperty<IServiceProvider>(ApplicationServicesKey, value);
                }
            }
    
            public IFeatureCollection ServerFeatures
            {
                get
                {
                    return GetProperty<IFeatureCollection>(ServerFeaturesKey);
                }
            }
    
            public IDictionary<string, object> Properties { get; }
    
            private T GetProperty<T>(string key)
            {
                object value;
                return Properties.TryGetValue(key, out value) ? (T)value : default(T);
            }
    
            private void SetProperty<T>(string key, T value)
            {
                Properties[key] = value;
            }
    
            public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> 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<RequestDelegate, RequestDelegate> middleware)方法时,就把管道注册到列表中

    Build()方法构建出RequestDelegate,这个委托链是asp.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<IHttpContextAccessor>();
                _formOptions = serviceProvider.GetRequiredService<IOptions<FormOptions>>().Value;
                _serviceScopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
            }
    
            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

    /// <summary>
        /// Represents an application.
        /// </summary>
        /// <typeparam name="TContext">The context associated with the application.</typeparam>
        public interface IHttpApplication<TContext>
        {
            /// <summary>
            /// Create a TContext given a collection of HTTP features.
            /// </summary>
            /// <param name="contextFeatures">A collection of HTTP features to be used for creating the TContext.</param>
            /// <returns>The created TContext.</returns>
            TContext CreateContext(IFeatureCollection contextFeatures);
    
            /// <summary>
            /// Asynchronously processes an TContext.
            /// </summary>
            /// <param name="context">The TContext that the operation will process.</param>
            Task ProcessRequestAsync(TContext context);
    
            /// <summary>
            /// Dispose a given TContext.
            /// </summary>
            /// <param name="context">The TContext to be disposed.</param>
            /// <param name="exception">The Exception thrown when processing did not complete successfully, otherwise null.</param>
            void DisposeContext(TContext context, Exception exception);
        }
    internal class HostingApplication : IHttpApplication<HostingApplication.Context>
        {
            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<Context> 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的管道中处理请求和响应

  • 相关阅读:
    # 学号 2017-2018-20172309 《程序设计与数据结构》第十一周学习总结
    学号 2017-2018-20172309 《程序设计与数据结构》实验四报告
    # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
    学号 2017-2018-20172309 《程序设计与数据结构》第10周学习总结
    2017-2018-20172309 『Java程序设计』课程 结对编程练习_四则运算_第三周
    20172308 实验三《Java面向对象程序设计 》实验报告
    20172308《程序设计与数据结构》第十周学习总结
    20172308《程序设计与数据结构》第九周学习总结
    2017-2018-2 1723 『Java程序设计』课程 结对编程练习_四则运算 第二周
    20172308《程序设计与数据结构》第八周学习总结
  • 原文地址:https://www.cnblogs.com/lanpingwang/p/12640775.html
Copyright © 2020-2023  润新知