Este artículo es un artículo espejo de traducción automática, por favor haga clic aquí para saltar al artículo original.

Vista: 59583|Respuesta: 1

[Fuente] ASP.NET Núcleo (7) Análisis en profundidad del código fuente del framework

[Copiar enlace]
Publicado el 24-3-2021 13:43:28 | | |
Revisión:

ASP.NET Core (VI) DI obtiene manualmente el método de inyectar objetos
https://www.itsvse.com/thread-9595-1-1.html

ASP.NET Core (cinco) se basa en transacciones distribuidas CAP
https://www.itsvse.com/thread-9593-1-1.html

ASP.NET Validación unificada de modelos de modelo del filtro Core(4)
https://www.itsvse.com/thread-9589-1-1.html

ASP.NET Core (iii) Crear dinámicamente instancias usando ActivatorUtilities
https://www.itsvse.com/thread-9488-1-1.html

ASP.NET Núcleo (2) Reiniciar la aplicación por código
https://www.itsvse.com/thread-9480-1-1.html

ASP.NET Core (1) utiliza caché Redis
https://www.itsvse.com/thread-9393-1-1.html
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.


asp.net Dirección del código fuente principal
https://www.itsvse.com/thread-9394-1-1.html


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)




Anterior:Informes de recién llegado tardío
Próximo:Error .NET Core en el paquete de procesamiento de fallos de Linux
Publicado el 2021-9-22 20:45:12 |
Aprende a aprender...
Renuncia:
Todo el software, materiales de programación o artículos publicados por Code Farmer Network son únicamente para fines de aprendizaje e investigación; El contenido anterior no se utilizará con fines comerciales o ilegales; de lo contrario, los usuarios asumirán todas las consecuencias. La información de este sitio proviene de Internet, y las disputas de derechos de autor no tienen nada que ver con este sitio. Debes eliminar completamente el contenido anterior de tu ordenador en un plazo de 24 horas desde la descarga. Si te gusta el programa, por favor apoya el software genuino, compra el registro y obtén mejores servicios genuinos. Si hay alguna infracción, por favor contáctanos por correo electrónico.

Mail To:help@itsvse.com