Revisión:
Empieza adjuntando la dirección de código abierto ASP.NET Core de GitHub
El inicio de sesión del hipervínculo es visible.
El inicio de sesión del hipervínculo es visible.
Tras crear un nuevo proyecto ASP.NET Core 3.1, el código del programa es el siguiente:
Profundizamos en el código de entrada combinado con el código fuente de GitHub.
Código de anfitrión:El inicio de sesión del hipervínculo es visible.
Método CreateDefaultBuilder
Aquí instanciamos un objeto HostBuilder, que hereda de IHostBuilder, y añadimos delegados definidos por el sistema, como :appsettings.json, appsettings. {env. NombreAmbiente}.json archivo de configuración, que eventualmente devolverá: interfaz IHostBuilder.
Código HostBuilder:El inicio de sesión del hipervínculo es visible.
El método Build acabará siendo llamado.
Build pública IHost()
{ if (_hostBuilt) { lanzar un nuevo InvalidOperationException(SR. BuildCalled); } _hostBuilt = verdadero;
BuildHostConfiguration(); CrearEntornoAnfitrion(); CrearHostConstructorContexto(); BuildAppConfiguration(); CreateServiceProvider();
return _appServices.GetRequiredService<IHost>();
} Método BuildHostConfiguration
_hostConfiguration privada de Iconfiguración; IConfigurationBuilder configBuilder = nuevo ConfigurationBuilder() Llama al delegado para añadir configuración a su vez
Método CreateHostingEnvironment
Ambiente de Anfitrión privado _hostingEnvironment; _hostingEnvironment = nuevo Entorno de Alojamiento()
{ NombreAplicación = _hostConfiguration[HostDefaults.ApplicationKey], NombreEntorno = _hostConfiguration[HostDefaults.EnvironmentKey] ?? Entornos. Producción, ContentRootPath = ResolveContentRootPath(_hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory), }; Método CreateHostBuilderContext
privado HostBuilderContext _hostBuilderContext; _hostBuilderContext = nuevo HostBuilderContext(Propiedades)
{ HostingEnvironment = _hostingEnvironment, Configuración = _hostConfiguration }; Método BuildAppConfiguration
Integrar de nuevo la información de configuración
IConfigurationBuilder configBuilder = nuevo ConfigurationBuilder() . SetBasePath(_hostingEnvironment.ContentRootPath) . AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true); _appConfiguration = configBuilder.Build(); _hostBuilderContext.Configuración = _appConfiguration; Método CreateServiceProvider
var servicios = nueva ServiceCollection(); Registrar un servicio, llamar a un delegado y añadir un servicio definido por el usuario.
Método de extensión GenericHostBuilderExtensions
El inicio de sesión del hipervínculo es visible.
Método de extensión ConfigureWebHost
Para registrar GenericWebHostService como servicio backend:
Constructor. ConfigureServices((contexto, servicios) = > servicios. AddHostedService<GenericWebHostService>()); Código GenericWebHostService:El inicio de sesión del hipervínculo es visible.
Task StartAsync async publico(CancellationToken cancellationToken) { HostingEventSource.Log.HostStart();
var serverAddressesFeature = Server.Features.Get<IServerAddressesFeature>(); var addresses = servidorDireccionesFuncional?. Direcciones; si (direcciones != nulo && !direcciones. IsReadOnly & & direcciones. Cuenta == 0) { var urls = Configuration[WebHostDefaults.ServerUrlsKey]; si (!string. IsNullOrEmpty(urls)) { ¡FunciónDireccionesservidor!. PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);
Foreach (valor var en URLs. Split('; ', StringSplitOptions.RemoveEmptyNtries)) { direcciones. Suma (valor); } } }
¿SolicitarDelegar? aplicación = nulo;
Prueba { var configure = Options.ConfigureApplication;
if (configure == null) { lanzar un nuevo InvalidOperationException($"No se configura ninguna aplicación. Por favor, especifica una aplicación a través de IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, o especificando el ensamblador de inicio mediante {nameof(WebHostDefaults.StartupAssemblyKey)} en el configuración de alojamiento web."); }
var builder = ApplicationBuilderFactory.CreateBuilder(Server.Features);
foreach (var filter en StartupFilters.Reverse()) { configurar = filtro. Configure(configure); }
configure(builder);
Construir la cadena de solicitudes aplicación = constructor. Build(); } catch (excepción ex) { Logger.ApplicationError(ex);
si (! Opciones.WebHostOptions.CaptureStartupErrors) { lanzar; }
var showDetailedErrors = HostingEnvironment.IsDevelopment() || Opciones.WebHostOptions.ErroresDetallados;
aplicación = ErrorPáginaConstructorErrorPáginaAplicación(HostingEnvironment.ContentRootFileProvider, Logger, showDetailedErrors, ej); }
var httpApplication = new HostingApplication(application, Logger, DiagnosticListener, HttpContextFactory);
await Server.StartAsync(httpApplication, cancellationToken);
si (endereza != nulo) { Foreach (dirección var en direcciones) { RegistradorTemporal.EscuchandoEnDirección (dirección); } }
if (Logger.IsEnabled(LogLevel.Debug)) { foreach (ensamblador var en Options.WebHostOptions.GetFinalHostingStartupAssemblies()) { Logger.StartupAssemblyLoaded(assembly); } }
if (Options.HostingStartupExceptions != null) { foreach (var exception en Options.HostingStartupExceptions.InnerExceptions) { Logger.HostingStartupAssemblyError(exception); } } }
var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions); El inicio de sesión del hipervínculo es visible.
Método de extensión WebHostBuilderExtensions
Proporciona un objeto StartType para llamadas a IWebHostBuilder.
este IWebHostBuilder hostBuilder si (hostBuilder es ISupportsStartup supportsStartup)
{ return supportsStartup.UseStartup(startupType);
} El inicio de sesión del hipervínculo es visible.
GenericWebHostBuilder Método Privado GenericWebHostBuilder
Instancia dinámicamente nuestro objeto Startup:
¿Instancia?? = ActivatorUtilities.CreateInstance(nuevo HostServiceProvider(webHostBuilderContext), Tipo de inicio); contexto. Propiedades[_startupKey] = instancia; Busca el método ConfigureServices
var configureServicesBuilder = StartupLoader.FindConfigureServicesDelegate(startupType, context. HostingEnvironment.EnvironmentName); var configureServices = configureServicesBuilder.Build(instance);
ConfigureServicesBuilder estático interno FindConfigureServicesDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo startupType, string NombreAmbiente) { var servicesMethod = FindMethod(startupType, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false) ?? FindMethod(startupType, "Configure{0}Services", environmentName, typeof(void), required: false); return new ConfigureServicesBuilder(servicesMethod); Busca el método ConfigureContainer
var configureContainerBuilder = StartupLoader.FindConfigureContainerDelegate(startupType, context. HostingEnvironment.EnvironmentName);
ConfigureContainerBuilder estático interno FindConfigureContainerDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo startupType, string NombreAmbiente) { var configureMethod = FindMethod(startupType, "Configure{0}Container", environmentName, typeof(void), required: false); return new ConfigureContainerBuilder(configureMethod); } Busca el método Configure
configureBuilder = StartupLoader.FindConfigureDelegate(startupType, context. HostingEnvironment.EnvironmentName);
ConfigureBuilder estático interno FindConfigureDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo TipoInicio, NombreDeEntorno de cadena)
{ var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true)!; return new ConfigureBuilder(configureMethod);
} Llamado por el método Build de ConfigureBuilder, el código fuente es el siguiente:
clase privada ConfigureBuilder { ConfigureBuilder público (MethodInfo configure) { MethodInfo = configure; }
MethodInfo MethodInfo público { get; }
Construcción de acción<IApplicationBuilder> pública (instancia de objetos) { return (applicationBuilder) => Invoke(instance, applicationBuilder); }
empty privado Invoke(instancia de objetos, IApplicationBuilder builder) { var serviceProvider = builder. Servicios de Aplicaciones; var parameterInfos = MethodInfo.GetParameters(); var parameters = new object[parameterInfos.Length]; para (var index = 0; índice < parámetroInfos.Length; index++) { var parameterInfo = parameterInfos[index]; if (parameterInfo.ParameterType == typeof(IApplicationBuilder)) { parámetros[index] = constructor; } si no, { Prueba { parameters[index] = ServiceProvider.GetRequiredService(parameterInfo.ParameterType); } catch (excepción ex) { lanzar un nuevo InvalidOperationException( Resources.FormatMiddlewareFilter_ServiceResolutionFail( parameterInfo.ParameterType.NombreCompleto, parameterInfo.Name, MethodInfo.Name, MethodInfo.DeclaringType.FullName), ex); } } } MethodInfo.Invoke(instancia, parámetros); } } Método de ejecución
Dirección del método de extensión HostingAbstractionsHostExtensions:
El inicio de sesión del hipervínculo es visible.
Finalmente llama:
/// <summary> Ejecuta una aplicación y devuelve una Tarea que solo se completa cuando se activa el token o se activa el apagado. /// </summary> <param name="host">El <ver cref="IHost"/> to run.</param> <param name="token">El token para activar el apagado.</param> <returns>El <véase cref="Task"/> que representa la operación asíncrona.</returns> Task RunAsync estático público async (este host IHost, token CancellationToken = default) { Prueba { Espera al anfitrión. StartAsync (token). ConfigureAwait(false);
Espera al anfitrión. EsperaForShutdownAsync (token). ConfigureAwait(false); } por fin { if (host es IAsyncDisposable asyncDisposable) { await asyncDisposable.DisposeAsync(). ConfigureAwait(false); } si no, { anfitrión. Dispone(); }
} } Antes, cuando estaba creando un servicio, me registraba para el servicio IHost, y el código es el siguiente:
servicios. <IHost>AddSingleton(_ => { return new Internal.Host(_appServices, _appServices.GetRequiredService<IHostApplicationLifetime>(), _appServices.GetRequiredService<ILogger<Internal.Host>>(), _appServices.GetRequiredService<IHostLifetime>(), _appServices.GetRequiredService<IOptions<HostOptions>>()); }); Método StartAsync
Dirección:El inicio de sesión del hipervínculo es visible.
Task StartAsync async publico(CancellationToken cancellationToken = default) { _logger. Iniciando();
usando var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _applicationLifetime.ApplicationStopping); CancellationToken combinedCancellationToken = combinedCancellationTokenSource.Token;
await _hostLifetime.WaitForStartAsync(combinedCancellationToken). ConfigureAwait(false);
combinedCancellationToken.ThrowIfCancellationRequested(); _hostedServices = Services.GetService<IEnumerable<IHostedService>>();
foreach (IHostedService hostedService en _hostedServices) { // Fire IHostedService.Start await hostedService.StartAsync(combinedCancellationToken). ConfigureAwait(false);
if (hostedService es BackgroundService backgroundService) { _ = HandleBackgroundException(backgroundService); } }
Fuego IHostApplicationLifetime.Iniciado _applicationLifetime.NotificarIniciado();
_logger. Iniciado(); } (Fin)
|