ASP.NET Core 5.0 (1) - 模板项目创建及解析

本文不是针对初学者的入门文章,而是从asp.net core 5.0 源码的角度分析程序是如何加载并运行的。

创建 ASP.NET Core Web App(MVC) 模板项目

运行 VS2019 并创建新的ASP.NET Core Web App(Model-View-Controller) 模板项目, 在创建向导中 Target Framework选择 .Net 5.0,我们暂时不需要任何的身份验证 所以 Authentication Type
选择 None,项目创建完成后目录结构类似于:

MVCTemplate.jpg

直接 F5 运行,浏览器会默认打开 http://localhost:5000/ 的地址,模板只含有两个页面 Home 及 Privacy

分析模板代码

下面来分析主程序,打开Program.cs

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup();
                });
    }

CreateHostBuilder 方法会创建并配置一个 builder 对象,然后调用Build方法创建一个IHost的实例,最后调用Run 方法启动host。
下面一步步分析这段代码。
首先Host是一个静态类,命名空间是Microsoft.Extensions.Hosting, 这个静态类中只包含两个静态方法,还是重载方法, 只参数不同

public static IHostBuilder CreateDefaultBuilder();
public static IHostBuilder CreateDefaultBuilder(string[] args);

来看看CreateDefaultBuilder具体的实现,去掉了一些具体的配置代码

public static IHostBuilder CreateDefaultBuilder(string[] args)
        {
            var builder = new HostBuilder();

            builder.UseContentRoot(Directory.GetCurrentDirectory());
            builder.ConfigureHostConfiguration(config =>
            {
               //加载DOTNET_ 环境变量和命令行参数
            });

            builder.ConfigureAppConfiguration((hostingContext, config) =>
            {
                //添加json配置文件, user secret,环境变量和命令行参数
            })
            .ConfigureLogging((hostingContext, logging) =>
            {
                //添加log:Event log,Console log,Debug, Event source,配置文件的log
            })
            .UseDefaultServiceProvider((context, options) =>
            {
              //配置依赖注入服务的验证信息
            });

            return builder;
        }

通过调用此方法就初始化好了一个IHostBuilder的实例(HostBuilder)
,至此所有配置的加载以及代码都是针对通用宿主(generic host),没有针对asp.net core 或 HTTP 请求的任何代码,在这个通用宿主的基础上我们可以设置成控制台程序,worker service,以及asp.net core 应用。
要把程序设成asp.net core, 程序调用IHostBuilder的一个扩展方法ConfigureWebHostDefaults,这个方法位于静态类GenericHostBuilderExtensions 中, 调用此方法是为hosting web app加载一些默认的选项。

 public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action configure)
        {
            if (configure is null)
            {
                throw new ArgumentNullException(nameof(configure));
            }

            return builder.ConfigureWebHost(webHostBuilder =>
            {
                WebHost.ConfigureWebDefaults(webHostBuilder);

                configure(webHostBuilder);
            });
        }

此方法中继续调用IHostBuilder的另外一个扩展方法ConfigureWebHost

        public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action configure, Action configureWebHostBuilder)
        {
            //省略一些参数的检查代码

            // Light up custom implementations namely ConfigureHostBuilder which throws.
            if (builder is ISupportsConfigureWebHost supportsConfigureWebHost)
            {
                return supportsConfigureWebHost.ConfigureWebHost(configure, configureWebHostBuilder);
            }

            var webHostBuilderOptions = new WebHostBuilderOptions();
            configureWebHostBuilder(webHostBuilderOptions);
            var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions);
            configure(webhostBuilder);
            builder.ConfigureServices((context, services) => services.AddHostedService());
            return builder;
        }

在ConfigureWebHost中,首先创建一个GenericWebHostBuilder
的对象,然后调用的传入的委托方法,在上一个ConfigureWebHostDefaults方法中,传入的委托方法是

webHostBuilder =>
            {
                WebHost.ConfigureWebDefaults(webHostBuilder);

                configure(webHostBuilder);
            }

委托方法先是调用的静态类WebHost
)
中的ConfigureWebDefaults,然后接着调用上一级传入的委托方法及Program.cs中传入的

webBuilder =>
                {
                    webBuilder.UseStartup();
                }

ConfigureWebHostDefaults

下面概括一下这个扩展方法

  • 添加 ASPNETCORE_ 开头的环境变量
  • 注册 GenericHostService(详见ConfigureWebHost方法), 这个类是IHostService的一个实现,这个类实现了让asp.net core 可以使用 generic host
  • 配置 Kestrel 当作默认Http Server 服务,反向代理伺服器(例如IIS,Nginx,Apache)会把接受http请求,并转发给Kestrel
  • 注册服务HostFilteringStartupFilter
  • 在Windows上启动IIS 集成
  • 注册路由服务

HostBuilder

这是一个非常重要的类,前面我们讲到了CreateDefaultBuilder是用来初始化一个IHostBuilder的实例,这个实例的默认实现就是HostBuilder,前面讲到的所有配置信息都是应用到这个类的实例的,这个类里定义了几个委托的list集合

private List> _configureHostConfigActions = new List>();
private List> _configureAppConfigActions = new List>();
private List> _configureServicesActions = new List>();
private List _configureContainerActions = new List();

前面我们看到的几乎所有的加载设置,服务之类的都是添加到对应的委托集合中,然后这些委托会在后续的Build方法中被循环调用。

总结

我们今天创建了一个asp.net core 5.0 mvc模板项目,并解释了CreateHostBuilder做的几件事情

  • 创建一个IHostBuilder的实例并加载一些针对generic host的设置,环境变量的添加、json配置文件加载、log等
  • 接着调用ConfigureWebHostDefaults并宿主配置成能asp.net core的程序

接下来的一篇文章我会解释一下Build这个方法。

你可能感兴趣的:(ASP.NET Core 5.0 (1) - 模板项目创建及解析)