学习ASP.NET Core, 怎能不了解请求处理管道[6]: 管道是如何随着WebHost的开启被构建出来的?
2016-11-23 08:45
1381 查看
注册的服务器和中间件共同构成了ASP.NET Core用于处理请求的管道, 这样一个管道是在我们启动作为应用宿主的WebHost时构建出来的。要深刻了解这个管道是如何被构建出来的,我们就必须对WebHost和它的创建者WebHostBuilder这个重要的对象具有深刻的理解。[本文已经同步到《ASP.NET Core框架揭秘》之中]
我们多次提到ASP.NET Core管道在构建和进行请求处理过程中广泛使用到了依赖注入。依赖注入只要体现在:ASP.NET Core框架以及应用程序会根据需要注册一系列的服务,这些服务会在WebHost启动的时候被用来创建一个ServiceProvider对象,管道在进行请求处理过程所需的任何服务对象都可以从这个ServiceProvider对象中获取。IWebHost接口的Services属性返回的就是这么一个ServiceProvider对象。
具有如下定义的WebHost类是对IWebHost接口的默认实现,我们默认使用的WebHost就是这么一个对象。一般来说,WebHost是通过对应的WebHostBuilder创建的,当后者通过调用构造函数创建一个WebHost对象的时候,需要提供四个参数,它们分别是直接注册到WebHostBuilder上面的服务(appServices)和由此创建的ServiceProvider(hostingServiceProvider),针对WebHost的选项设置(options)和配置(config)。
如下面的代码片段所示,WebHostOptions具有七个属性成员。这些属性都是可读可写的,我们可以调用默认无参构造函数创建一个空的WebHostOptions对象,通过手工为这些属性赋值的方式来设置对应的选项。除此之外,我们可以将这些选项设置定义在配置中,并利用对应的Configuration对象来创建一个WebHostOptions对象。
注册服务:获取Startup对象并利用它完成服务的注册。
中间件注册:利用获取的Startup对象完成中间件的注册。
设置并开启服务器:获取注册到WebHostBuilder上的服务器并为之设置监听地址,最后启动服务器。
接下来我们按照这个步骤定义一个同名的类型来模式真实WebHost的实现逻辑。如下面的代码片段所示,这个模拟的WebHost和真正的WebHost的构造函数具有完全一致的参数列表,我们定义了对应的字段来保存这些参数值。除此之外,我们会创建一个ApplicationLifetime对象并将其注册到提供个ServiceCollection,在WebHost开启和关闭之后我们会利用它发送相应的通知。
我们接下来看WebHost除Start方法之外的其他成员的定义。只读属性Services返回一个ServiceProvider对象,我们将在完成所有服务注册工作之后利用ServiceCollection对象创建这个对象,所以只要实现具有相关的服务注册,我们就能够利用它得到对应的服务对象。只读属性ServerFeatures返回服务器的特性集合,而服务器本身则直接利用上述这个ServiceProvider获得。当MyWebHost对象因Dispose方法的调用而被回收之后,我们会对ServiceProvider实施回收 工作。在实施回收的前后,我们利用ApplicationLifetime发送相应的信号。
真正开启WebHost的实现体现在如下所示的代码片段中。我们直接利用WebHostBuilder提供ServiceProvider获取一个Startup对象,并调用其ConfigureServices方法完成服务的注册,作为参数的ServiceCollection对象也是由WebHostBuilder提供的。当所有的服务注册工作完成之后,我们利用最新的ServiceCollection对象创建一个ServiceProvider对象,并利用此对象对Services属性进行赋值。在后续管道构建过程,以及管道在处理请求过程中所使用的服务均是从这个ServiceProvider中提取的。
当服务注册结束并成功创建出ServiceProvider之后,接下来的工作就是注册中间件了。通过上面的介绍我们知道,中间件的注册既可以利用Startup来完成,也可以利用注册的StartupFilter来实现,为此我们利用最新构建的ServiceProvider获取所有注册的StartupFilter,并结合之前提取的Startup对象创建了一个用于注册中间的委托链(最终体现为一个Action<IApplicationBuilder>对象)。我们最终执行这个委托链完成了对所有中间件的注册,执行过程中作为参数的ApplicationBuilder对象同样是通过ServiceProvider提取出来的。
再此之后,我们利用ServiceProvider提取出注册在WebHostBuiler上的服务器。如果服务器的监听地址尚未指定,我们在开启服务器之前必须指定。通过前面对服务器的介绍,我们知道监听地址保存在服务器的一个名为ServerAddressesFeature的特性中,而用户设置的监听地址则保存在配置中,对应的Key为“urls”,所以我们将从配置中提取的地址列表添加到ServerAddressesFeature特性中。如果监听地址不曾配置,我们会为之指定一个默认的地址,即“http://localhost:5000”。
一切就绪的服务器通过调用Start方法开启,该方法接收一个HttpApplication对象作为参数。通过前面的介绍我们知道这个HttpApplication对象可以视为对所有注册中间件和应用的封装,服务器将接收到的请求传递给它作后续处理。我们默认创建的HttpApplication是一个HostingApplication对象,而构建过程中需要提供四个对象,它们分别是代表中间件链表的RequestDelegate对象,用于日志记录和诊断的Logger和DiagnosticSource,以及用来创建HTTP上下文的HttpContextFactory,除了第一个通过调用ApplicationBuilder的Build方法创建之外,其余的都是通过ServiceProvider提取的。在服务器被成功开启之后,我们利用ApplicationLifetime对外发送应用启动的通知。
ConfigureServices方法让我们可以直接将我们所需的服务注册到WebHostBuilder上面。ASP.NET Core具有两种注册服务的途径,一种是将服务注册实现在启动类的ConfigureServices方法中,另一种服务注册的方式就是调用这个方法。对于前者,服务实际上是在开启WebHost的时候调用Startup对象的ConfigureServices进行注册的;至于后者,注册的服务将直接提供给创建的WebHost。UseLoggerFactory 和ConfigureLogging方法与日志记录有关,前者帮助我们设置一个默认的LoggerFactory,后者则对LoggerFactory进行相关设置,最重要的设置就是添加相应的LoggerProvider。GetSetting和UseSetting以键值对的形式获取和设置一些配置。
如上面的代码片段所示,我们创建了一个Configuration类型的字段(_config)来体现应用默认使用的配置,它默认采用环境变量(用于过滤环境变量的前缀为“ASPNETCORE_”)作为配置源,GetSetting和UseSetting方法操作的均为这个对象。另一个字段_loggerFactory表示默认使用的LoggerFactory,UseLoggerFactory方法指定的LoggerFactory用来对这个字段进行赋值。ConfigureLogging和ConfigureServices方法具有类似的定义,调用它们提供的委托对象都保存在一个集合之中,以待后用。
我们实现WebHostBuilder的核心方法Build来创建一个WebHost对象。通过上面的定义我们知道一个WebHostBuilder能够最终运行起来需要从ServiceProvider提供很多必需的服务,而这些服务最初都必需通过WebHostBuilder来注册,所以Build方法除了调用构造函数创建并返回一个WebHost对象之外,余下的工作就是注册这些必需的服务。我们可以简单列一列那些服务是必需的,如下所示的是一个不完全列表。
用于注册服务和中间件的Startup对象。
用来创建Logger的LoggerFactory对象
构建中间件链表的ApplicationBuilder对象
创建HTTP上下文的HttpContextFactory对象
用户实现诊断功能的DiagnosticSource对象
用来保存承载环境的HostingEnvironment对象
如下所示的定义在WebHostBuilder中的Build方法的定义。在这个方法中,我们按照上述这些系统服务以及用户服务(通过调用ConfigureServices方法注册的服务)的注册之后,创建并返回了一个WebHost对象。
虽然上面提供的WebHost和WebHostBuilder仅仅是WebHost和WebHostBuilder的模拟类。为了让读更加易于理解,我们刻意剔除了很多细节的东西,但是两者从实现原理角度来讲是完全一致的。不仅如此,我们自定义的这两个类型甚至可以执行运行的。
WebHostBuilder在创建WebHost的时候需要提供一个WebHostOptions对象,该对象最初是根据当前配置创建的。为了方便设置针对WebHostOptions的配置项,ASP.NET Core为我们定义了如下一系列的扩展方法,这些方法最终调用的也是这个UseSettings方法。
虽然服务器是必需的,但是WebHostBuilder并没有专门定义一个用于注册服务的方法,这是因为服务器也是作为一项基本的服务进行注册的。但是我们可以调用如下一个扩展方法UseServer实现针对服务器的注册,至于另一个扩展方法UseUrls,我们可以调用它来为注册的服务器设置监听地址。
目录
一、WebHost
WebHostOptions
构建管道的三个步骤
二、WebHostBuilder
WebHost的创建
几个常用的扩展方法
一、WebHost
WebHostOptions
构建管道的三个步骤
二、WebHostBuilder
WebHost的创建
几个常用的扩展方法
一、WebHost
顾名思义,WebHost被作为Web应用的宿主,应用的启动和关闭都是通过启动或者关闭对应WebHost的方式来实现的。这里所说的WebHost是对所有实现了IWebHost接口的所有类型及其对应对象的统称。IWebHost接口具有如下三个基本成员,其中Start方法用于启动宿主程序。我们编程中通常会调用它的一个扩展方法Run来启动WebHost,实际上背后调用的其实还是这个Start方法。当WebHost启动之后,注册的服务器变开始了针对请求的监听,所以WebHost需要具有与服务器相关的一些特性,这些特性就保存在通过属性ServerFeatures返回的特性集合中。public interface IWebHost : IDisposable
{
void Start();
IFeatureCollection ServerFeatures{ get;}
IServiceProvider Services{ get;}
}
我们多次提到ASP.NET Core管道在构建和进行请求处理过程中广泛使用到了依赖注入。依赖注入只要体现在:ASP.NET Core框架以及应用程序会根据需要注册一系列的服务,这些服务会在WebHost启动的时候被用来创建一个ServiceProvider对象,管道在进行请求处理过程所需的任何服务对象都可以从这个ServiceProvider对象中获取。IWebHost接口的Services属性返回的就是这么一个ServiceProvider对象。
具有如下定义的WebHost类是对IWebHost接口的默认实现,我们默认使用的WebHost就是这么一个对象。一般来说,WebHost是通过对应的WebHostBuilder创建的,当后者通过调用构造函数创建一个WebHost对象的时候,需要提供四个参数,它们分别是直接注册到WebHostBuilder上面的服务(appServices)和由此创建的ServiceProvider(hostingServiceProvider),针对WebHost的选项设置(options)和配置(config)。
[code]public class WebHost : IWebHost
{
public IFeatureCollection ServerFeatures{ get;}
public IServiceProvider Services{ get;}
public WebHost(
IServiceCollection appServices,
IServiceProvider hostingServiceProvider,
WebHostOptions options,
IConfiguration config);
public void Dispose();
public void Start();
}
WebHostOptions
顾名思义,一个WebHostOptions对象为构建的WebHost对象提供一些预定义的选项设置。这些选项设置很重要,它们决定由WebHost构建的管道进行内容加载以及异常处理等方面的行为。至于它具体携带着哪些选项设置,我们只需要看看这个类型具有怎样的属性成员。public class WebHostOptions
{
public string ApplicationName{ get; set;}
public bool DetailedErrors{ get; set;}
public bool CaptureStartupErrors{ get; set;}
public string Environment{ get; set;}
public string StartupAssembly{ get; set;}
public string WebRoot{ get; set;}
public string ContentRootPath{ get; set;}
public WebHostOptions()
public WebHostOptions(IConfiguration configuration)
}
如下面的代码片段所示,WebHostOptions具有七个属性成员。这些属性都是可读可写的,我们可以调用默认无参构造函数创建一个空的WebHostOptions对象,通过手工为这些属性赋值的方式来设置对应的选项。除此之外,我们可以将这些选项设置定义在配置中,并利用对应的Configuration对象来创建一个WebHostOptions对象。
构建管道的三个步骤
一般我们开启了作为应用宿主的WebHost,由注册的服务器和中间件构成的整个管道被构建起来,服务器开始绑定到基地址进行请求的监听。接下来我们就来着重聊聊WebHost在开启过程中都做了些什么。总的来说,WebHost的整个开启过程大体上可以分为如下三个步骤:注册服务:获取Startup对象并利用它完成服务的注册。
中间件注册:利用获取的Startup对象完成中间件的注册。
设置并开启服务器:获取注册到WebHostBuilder上的服务器并为之设置监听地址,最后启动服务器。
接下来我们按照这个步骤定义一个同名的类型来模式真实WebHost的实现逻辑。如下面的代码片段所示,这个模拟的WebHost和真正的WebHost的构造函数具有完全一致的参数列表,我们定义了对应的字段来保存这些参数值。除此之外,我们会创建一个ApplicationLifetime对象并将其注册到提供个ServiceCollection,在WebHost开启和关闭之后我们会利用它发送相应的通知。
[code]public class WebHost : IWebHost
{
private IServiceCollection _appServices;
private IServiceProvider _hostingServiceProvider;
private WebHostOptions _options;
private IConfiguration _config;
private ApplicationLifetime_applicationLifetime;
public WebHost(IServiceCollection appServices, IServiceProvider hostingServiceProvider, WebHostOptions options, IConfiguration config)
{
_appServices = appServices;
_hostingServiceProvider= hostingServiceProvider;
_options = options;
_config= config;
_applicationLifetime = new ApplicationLifetime();
appServices.AddSingleton<IApplicationLifetime>(_applicationLifetime);
}
…
}
我们接下来看WebHost除Start方法之外的其他成员的定义。只读属性Services返回一个ServiceProvider对象,我们将在完成所有服务注册工作之后利用ServiceCollection对象创建这个对象,所以只要实现具有相关的服务注册,我们就能够利用它得到对应的服务对象。只读属性ServerFeatures返回服务器的特性集合,而服务器本身则直接利用上述这个ServiceProvider获得。当MyWebHost对象因Dispose方法的调用而被回收之后,我们会对ServiceProvider实施回收 工作。在实施回收的前后,我们利用ApplicationLifetime发送相应的信号。
public class WebHost : IWebHost
{
private ApplicationLifetime _applicationLifetime;
public IServiceProvider Services{ get; private set;}
public IFeatureCollection ServerFeatures
{
get{ return this.Services.GetRequiredService<IServer>()?.Features;}
}
public void Dispose()
{
_applicationLifetime.StopApplication();
(this.Services as IDisposable)?.Dispose();
_applicationLifetime.NotifyStopped();
}
}
真正开启WebHost的实现体现在如下所示的代码片段中。我们直接利用WebHostBuilder提供ServiceProvider获取一个Startup对象,并调用其ConfigureServices方法完成服务的注册,作为参数的ServiceCollection对象也是由WebHostBuilder提供的。当所有的服务注册工作完成之后,我们利用最新的ServiceCollection对象创建一个ServiceProvider对象,并利用此对象对Services属性进行赋值。在后续管道构建过程,以及管道在处理请求过程中所使用的服务均是从这个ServiceProvider中提取的。
[code]public class WebHost : IWebHost
{
private IServiceCollection _appServices;
private IServiceProvider _hostingServiceProvider;
private WebHostOptions _options;
private IConfiguration _config;
private ApplicationLifetime_applicationLifetime;
public void Start()
{
//注册服务
IStartup startup = _hostingServiceProvider.GetRequiredService<IStartup>();
this.Services = startup.ConfigureServices(_appServices);
//注册中间件
Action<IApplicationBuilder> configure = startup.Configure;
configure = this.Services.GetServices<IStartupFilter>().Reverse().Aggregate(configure, (next, current) => current.Configure(next));
IApplicationBuilder appBuilder = this.Services.GetRequiredService<IApplicationBuilder>();
configure(appBuilder);
//为服务器设置监听地址
IServer server = this.Services.GetRequiredService<IServer>();
IServerAddressesFeature addressesFeature = server.Features.Get<IServerAddressesFeature>();
if (null != addressesFeature && !addressesFeature.Addresses.Any())
{
string addresses = _config["urls"] ?? "http://localhost:5000";
foreach (string address in addresses.Split(';'))
{
addressesFeature.Addresses.Add(address);
}
}
//启动服务器
RequestDelegate application = appBuilder.Build();
ILogger logger = this.Services.GetRequiredService <ILogger<MyWebHost>>();
DiagnosticSource diagnosticSource = this.Services.GetRequiredService<DiagnosticSource>();
IHttpContextFactory httpContextFactory = this.Services.GetRequiredService<IHttpContextFactory>();
server.Start(new HostingApplication(application, logger, diagnosticSource, httpContextFactory));
//对外发送通知
_applicationLifetime.NotifyStarted();
}
}
当服务注册结束并成功创建出ServiceProvider之后,接下来的工作就是注册中间件了。通过上面的介绍我们知道,中间件的注册既可以利用Startup来完成,也可以利用注册的StartupFilter来实现,为此我们利用最新构建的ServiceProvider获取所有注册的StartupFilter,并结合之前提取的Startup对象创建了一个用于注册中间的委托链(最终体现为一个Action<IApplicationBuilder>对象)。我们最终执行这个委托链完成了对所有中间件的注册,执行过程中作为参数的ApplicationBuilder对象同样是通过ServiceProvider提取出来的。
再此之后,我们利用ServiceProvider提取出注册在WebHostBuiler上的服务器。如果服务器的监听地址尚未指定,我们在开启服务器之前必须指定。通过前面对服务器的介绍,我们知道监听地址保存在服务器的一个名为ServerAddressesFeature的特性中,而用户设置的监听地址则保存在配置中,对应的Key为“urls”,所以我们将从配置中提取的地址列表添加到ServerAddressesFeature特性中。如果监听地址不曾配置,我们会为之指定一个默认的地址,即“http://localhost:5000”。
一切就绪的服务器通过调用Start方法开启,该方法接收一个HttpApplication对象作为参数。通过前面的介绍我们知道这个HttpApplication对象可以视为对所有注册中间件和应用的封装,服务器将接收到的请求传递给它作后续处理。我们默认创建的HttpApplication是一个HostingApplication对象,而构建过程中需要提供四个对象,它们分别是代表中间件链表的RequestDelegate对象,用于日志记录和诊断的Logger和DiagnosticSource,以及用来创建HTTP上下文的HttpContextFactory,除了第一个通过调用ApplicationBuilder的Build方法创建之外,其余的都是通过ServiceProvider提取的。在服务器被成功开启之后,我们利用ApplicationLifetime对外发送应用启动的通知。
二、WebHostBuilder
顾名思义,WebHostBuilder就是WebHost的创建者,所谓的WebHostBuilder是对所有实现了IWebHostBuilder接口的类型以及对应对象的统称。如下面的代码片段所示,IWebHostBuilder接口除了用来创建WebHost的核心方法Build之外,还具有其他一些额外的方法。public interface IWebHostBuilder
{
IWebHost Build();
IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices);
IWebHostBuilder UseLoggerFactory(ILoggerFactory loggerFactory);
IWebHostBuilder ConfigureLogging(Action<ILoggerFactory> configureLogging);
string GetSetting(string key);
IWebHostBuilder UseSetting(string key, string value);
}
ConfigureServices方法让我们可以直接将我们所需的服务注册到WebHostBuilder上面。ASP.NET Core具有两种注册服务的途径,一种是将服务注册实现在启动类的ConfigureServices方法中,另一种服务注册的方式就是调用这个方法。对于前者,服务实际上是在开启WebHost的时候调用Startup对象的ConfigureServices进行注册的;至于后者,注册的服务将直接提供给创建的WebHost。UseLoggerFactory 和ConfigureLogging方法与日志记录有关,前者帮助我们设置一个默认的LoggerFactory,后者则对LoggerFactory进行相关设置,最重要的设置就是添加相应的LoggerProvider。GetSetting和UseSetting以键值对的形式获取和设置一些配置。
WebHost的创建
ASP.NET Core定义了一个名为WebHostBuilder的类型作为对IWebHostBuilder接口的默认实现,我们同样采用定义模拟类型的形式来说明WebHostBuilder创建WebHost的实现原理。我们将这个模拟类型命名为,如下的代码片段展示了除Build方法之外的所有成员的定义。[code] public class WebHostBuilder : IWebHostBuilder
{
private List<Action<ILoggerFactory>> _configureLoggingDelegates = new List<Action<ILoggerFactory>>();
private List<Action<IServiceCollection>> _configureServicesDelegates = new List<Action<IServiceCollection>>();
private ILoggerFactory _loggerFactory = new LoggerFactory();
private IConfiguration _config = new ConfigurationBuilder().AddEnvironmentVariables("ASPNETCORE_").Build();
public IWebHostBuilder ConfigureLogging(Action<ILoggerFactory> configureLogging)
{
_configureLoggingDelegates.Add(configureLogging);
return this;
}
public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureServices)
{
_configureServicesDelegates.Add(configureServices);
return this;
}
public string GetSetting(string key)
{
return _config[key];
}
public IWebHostBuilder UseLoggerFactory(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
return this;
}
public IWebHostBuilder UseSetting(string key, string value)
{
_config[key] = value;
return this;
}
...
}
如上面的代码片段所示,我们创建了一个Configuration类型的字段(_config)来体现应用默认使用的配置,它默认采用环境变量(用于过滤环境变量的前缀为“ASPNETCORE_”)作为配置源,GetSetting和UseSetting方法操作的均为这个对象。另一个字段_loggerFactory表示默认使用的LoggerFactory,UseLoggerFactory方法指定的LoggerFactory用来对这个字段进行赋值。ConfigureLogging和ConfigureServices方法具有类似的定义,调用它们提供的委托对象都保存在一个集合之中,以待后用。
我们实现WebHostBuilder的核心方法Build来创建一个WebHost对象。通过上面的定义我们知道一个WebHostBuilder能够最终运行起来需要从ServiceProvider提供很多必需的服务,而这些服务最初都必需通过WebHostBuilder来注册,所以Build方法除了调用构造函数创建并返回一个WebHost对象之外,余下的工作就是注册这些必需的服务。我们可以简单列一列那些服务是必需的,如下所示的是一个不完全列表。
用于注册服务和中间件的Startup对象。
用来创建Logger的LoggerFactory对象
构建中间件链表的ApplicationBuilder对象
创建HTTP上下文的HttpContextFactory对象
用户实现诊断功能的DiagnosticSource对象
用来保存承载环境的HostingEnvironment对象
如下所示的定义在WebHostBuilder中的Build方法的定义。在这个方法中,我们按照上述这些系统服务以及用户服务(通过调用ConfigureServices方法注册的服务)的注册之后,创建并返回了一个WebHost对象。
[code] public class WebHostBuilder : IWebHostBuilder
{
private List<Action<ILoggerFactory>> _configureLoggingDelegates = new List<Action<ILoggerFactory>>();
private List<Action<IServiceCollection>> _configureServicesDelegates = new List<Action<IServiceCollection>>();
private ILoggerFactory _loggerFactory = new LoggerFactory();
private IConfiguration _config = new ConfigurationBuilder().AddInMemoryCollection().Build();
public IWebHost Build()
{
//根据配置创建WebHostOptions
WebHostOptions options = new WebHostOptions(_config);
//注册服务IStartup
IServiceCollection services = new ServiceCollection();
if (!string.IsNullOrEmpty(options.StartupAssembly))
{
Type startupType = StartupLoader.FindStartupType(options.StartupAssembly, options.Environment);
if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType))
{
services.AddSingleton(typeof(IStartup), startupType);
}
else
{
services.AddSingleton<IStartup>(_ => new ConventionBasedStartup(StartupLoader.LoadMethods(_, startupType, options.Environment)));
}
}
//注册ILoggerFactory
foreach (var configureLogging in _configureLoggingDelegates)
{
configureLogging(_loggerFactory);
}
services.AddSingleton<ILoggerFactory>(_loggerFactory);
//注册服务IApplicationBuilder,DiagnosticSource和IHttpContextFactory
services
.AddSingleton<IApplicationBuilder>(_ => new ApplicationBuilder(_))
.AddSingleton<DiagnosticSource>(new DiagnosticListener("Microsoft.AspNetCore"))
.AddSingleton<IHttpContextFactory, HttpContextFactory>()
.AddOptions()
.AddLogging()
.AddSingleton<IHostingEnvironment, HostingEnvironment>()
.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
//注册用户调用ConfigureServices方法设置的服务
foreach (var configureServices in _configureServicesDelegates)
{
configureServices(services);
}
//创建MyWebHost
return new WebHost(services, services.BuildServiceProvider(), options, _config);
}
}
虽然上面提供的WebHost和WebHostBuilder仅仅是WebHost和WebHostBuilder的模拟类。为了让读更加易于理解,我们刻意剔除了很多细节的东西,但是两者从实现原理角度来讲是完全一致的。不仅如此,我们自定义的这两个类型甚至可以执行运行的。
几个常用的扩展方法
WebHostBuilder在内部使用了配置,环境变量是默认采用的配置源,它的两个方法GetSetting和UseSetting以键值对的形式实现对配置项的获取和设置。除了UseSettings方法之外,我们还可以调用WebHostBuilder如下这个扩展方法UseConfiguration来进行配置项的设置,这个方法会将保存在指定Configuration中的配置原封不动地拷贝过来,它最终调用的依旧是UseSettings方法。[code] public static class HostingAbstractionsWebHostBuilderExtensions
{
public static IWebHostBuilder UseConfiguration(this IWebHostBuilder hostBuilder, IConfiguration configuration);
}
WebHostBuilder在创建WebHost的时候需要提供一个WebHostOptions对象,该对象最初是根据当前配置创建的。为了方便设置针对WebHostOptions的配置项,ASP.NET Core为我们定义了如下一系列的扩展方法,这些方法最终调用的也是这个UseSettings方法。
[code] public static class HostingAbstractionsWebHostBuilderExtensions
{
public static IWebHostBuilder CaptureStartupErrors(this IWebHostBuilder hostBuilder, bool captureStartupErrors);
public static IWebHostBuilder UseContentRoot(this IWebHostBuilder hostBuilder, string contentRoot);
public static IWebHostBuilder UseEnvironment(this IWebHostBuilder hostBuilder, string environment);
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, string startupAssemblyName);
public static IWebHostBuilder UseWebRoot(this IWebHostBuilder hostBuilder, string webRoot);
public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls);
}
虽然服务器是必需的,但是WebHostBuilder并没有专门定义一个用于注册服务的方法,这是因为服务器也是作为一项基本的服务进行注册的。但是我们可以调用如下一个扩展方法UseServer实现针对服务器的注册,至于另一个扩展方法UseUrls,我们可以调用它来为注册的服务器设置监听地址。
[code] public static class HostingAbstractionsWebHostBuilderExtensions
{
public static IWebHostBuilder UseServer(this IWebHostBuilder hostBuilder, IServer server);
public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls);
}
相关文章推荐
- 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的
- 学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位
- 学习ASP.NET Core,你必须知道“中间件”是什么?中间件如何注册?请求处理管道是如何通过中间件构建的?
- 学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位
- 学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?
- 学习ASP.NET Core, 怎能不了解请求处理管道[5]: 中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter
- 学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?
- 学习ASP.NET Core, 怎能不了解请求处理管道[4]: 应用的入口——Startup
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?
- 管道是如何随着WebHost的开启被构建出来的?
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[中]:管道如何处理请求
- ASP.NET Core应用针对静态文件请求的处理[5]: DefaultFilesMiddleware中间件如何显示默认页面
- 如果你想深刻理解ASP.NET Core请求处理管道,可以试着写一个自定义的Server
- ASP.NET Core真实管道详解[2]:Server是如何完成针对请求的监听、接收与响应的【上】
- ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求
- ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?
- 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[上]:采用管道处理请求
- ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程
- 如何ASP.NET Core Razor中处理Ajax请求
- ASP.NET Core应用针对静态文件请求的处理[4]: DirectoryBrowserMiddleware中间件如何呈现目录结构