ASP. NET Core 2.0: 7. A picture shows the secret behind startup, asp. netcore

Source: Internet
Author: User
Tags webhost

ASP. NET Core 2.0: 7. A picture shows the secret behind startup, asp. netcore

Why can we configure dependency injection and pipelines in the "standalone" Class of Startup?

When is it instantiated and called?

How does IServiceCollection services in the parameter come from?

How is the processing pipeline built?

What preparations did the system "Silently" perform during the startup process?

The previous article talked about ASP.. NET Core dependency injection (Series directory). Its configuration is the ConfigureServices (IServiceCollection services) method in the Startup file, and the Startup class does not inherit any classes or interfaces. If you think about it in depth, there may be many problems similar to the ones listed above. We will use a picture below to see through it.

I. Overall Flowchart

First, you can click to view a large image or download it, And then enlarge it.


Figure 1 (click to enlarge)

Ii. WebHostBuilder

After the Main method, the application creates and configures WebHostBuilder by calling the Create DefaultBuilder method,

 1 public class WebHostBuilder : IWebHostBuilder
 2     {
 3         private readonly List<Action<WebHostBuilderContext, IServiceCollection>> _configureServicesDelegates;
 4 
 5         private IConfiguration _config;
 6         public IWebHostBuilder UseSetting(string key, string value)
 7         {
 8             _config[key] = value;
 9             return this;
10         }
22         public IWebHostBuilder ConfigureServices(Action<WebHostBuilderContext, IServiceCollection> configureServices)
23         {
24             if (configureServices == null)
25             {
26                 throw new ArgumentNullException(nameof(configureServices));
27             }
29             _configureServicesDelegates.Add(configureServices);
30             return this;
31         }
32     }

WebHostBuilder has an important set ① private readonly List <Action <WebHostBuilderContext, IServiceCollection> _ configureServicesDelegates; which is used to add the required actions.

UseSetting is a Key-Value setting method. Common configurations are written to _ config through this method.

Iii. UseStartup <Startup> ()

Create ­ ultbuilder and call UseStartup <Startup> () to specify Startup as the Startup class.

  public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
        {
            var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name;

            return hostBuilder
                .UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName)
                .ConfigureServices(services =>
                {
                    if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo()))
                    {
                        services.AddSingleton(typeof(IStartup), startupType);
                    }
                    else
                    {
                        services.AddSingleton(typeof(IStartup), sp =>
                        {
                            var hostingEnvironment = sp.GetRequiredService<IHostingEnvironment>();
                            return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName));
                        });
                    }
                });
        }

First, obtain the AssemblyName corresponding to the Startup class, and call the UseSetting method to set it to the value of WebHostDefaults. ApplicationKey ("applicationName.

Call the ② ConfigureServices method of WebHostBuilder to write an Action to configureServicesDelegates of WebHostBuilder.

This Action means that if the specified startupType class is a class that implements IStartup, it will be registered to the ServiceCollection service through AddSingleton. If not, then convert it to ConventionBasedStartup, which implements the IStartup class and then register it. The LoadMethods () method of StartupLoader is involved here. The methods such as "ConfigureServices" and "Configure {environmentName} Services" are searched through strings.

Note: Only an Action is written to configureServicesDelegates, instead of registering IStartup, because this Action has not been executed and services does not exist. Just as the Bodhisattva said to Ba Jie: You should wait in Gao Lao Zhuang first. In the future, there will be a monk who will lead the ServiceCollection services team and you will join them.

In fact, several UseXXX methods in the Create defadefabuilder method also write the corresponding Action into configureServicesDelegates through ConfigureServices, waiting for Tang Miao to arrive.

4. WebHostBuilder. Build ()

After the WebHostBuilder is created and configured, you can use the Build method to create a WebHost. The first is BuildCommonServices,

1 private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
  2         {
  3 //...omitted...
  4 var services = new ServiceCollection();
  5 services.AddSingleton(_hostingEnvironment);
  6 services.AddSingleton(_context);
  7 //....various Add....
  9 foreach (var configureServices in _configureServicesDelegates)
10 {
11 configureServices(_context, services);
12 }
14 return services;
15 }

In this method, ServiceCollection services (a collection team headed by Tang Seng) is created, and a lot of content is registered through various Add methods (Wukong is collected ), ③ each Action saved in configureServicesDelegates before foreach is passed into services for execution one by one, and the previously registered content is registered to services. Startup (eight rings) is included here ), note that only the registration is performed, but the Startup method is not executed.

After this service is returned by BuildCommonServices, it is assigned to hostingServices. Then, hostingServices generates applicationServices by Clone (), and then GetProviderFromFactory (hostingServices) generates an IServiceProvider hostingServiceProvider. after a series of processing, you can create a WebHost.

var host = new WebHost(
    applicationServices,
    hostingServiceProvider,
    _options,
    _config,
    hostingStartupErrors);

host.Initialize();

Pass the generated applicationServices and hostingServiceProvider as parameters to the new WebHost. The following is the Initialize () of the WebHost ().

5. WebHost. Initialize ()

The main task of WebHost Initialize () is BuildApplication ().

EnsureApplicationServices ():Private IServiceProvider _ applicationServices used to process WebHost. ④ the ConfigureServices method of Startup is called here.

_startup = _hostingServiceProvider.GetRequiredService<IStartup>();
_applicationServices = _startup.ConfigureServices(_applicationServiceCollection);

Get our _ startup through GetRequiredService <IStartup> () and call the ⑤ ConfigureServices method of this _ startup. This is the ConfigureServices method of the startup class for dependency injection.

Therefore, _ applicationServices is an IServiceProvider that is re-generated based on _ applicationServiceCollection and the content we registered in _ startup.

EnsureServer () ⑥:Use GetRequiredService <IServer> () to obtain the Server and configure the listening address.

var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>();
var builder = builderFactory.CreateBuilder(Server.Features);
builder.ApplicationServices = _applicationServices;

Obtain IApplicationBuilderFactory, create IApplicationBuilder through it 7, and assign the _ applicationServices created above to its ApplicationServices. It also has an important set of _ components.

private readonly IList<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();

From the type of _ components, we can see that it is actually a collection of middleware, and it is time to call our _ startup Configure method.

Obtain the defined IStartupFilter, define foreach, IStartupFilter, and write the configured middleware into _ components together with the Configure method of _ startup, and then create RequestDelegate _ application through Build,

Process _ components in Build () to generate a request processing pipeline. The IStartupFilter and pipeline generation sections will be described in the next article.

Vi. WebHost. Run ()

After the WebHost is created, the last step is Run. The WebHost Run () will call its method StartAsync ()

var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>();
var builder = builderFactory.CreateBuilder(Server.Features);
builder.ApplicationServices = _applicationServices;

In the previous article, we know that the request is handled by Server listener => httpContext => Application, therefore, first input the created _ application and an httpContextFactory to generate a HostingApplication and pass the HostingApplication to the StartAsync () of the Server. After the Server listens to the request, the subsequent work is completed by HostingApplication.

The ⑩ hostedServiceExecutor. StartAsync () method is used to enable a service running in the background. Operations that need to be run in the background, such as regular cache refresh, can be put here.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.