Este artigo é um artigo espelhado de tradução automática, por favor clique aqui para ir para o artigo original.

Vista: 59583|Resposta: 1

[Fonte] ASP.NET Core (7) Análise aprofundada do código-fonte do framework

[Copiar link]
Postado em 2021-3-24 13:43:28 | | |
Revisar:

ASP.NET Core (VI) DI obtém manualmente o método de injeção de objetos
https://www.itsvse.com/thread-9595-1-1.html

ASP.NET Core (cinco) é baseado em transações distribuídas CAP
https://www.itsvse.com/thread-9593-1-1.html

ASP.NET Validação unificada do modelo ModelState do filtro Core(4)
https://www.itsvse.com/thread-9589-1-1.html

ASP.NET Core (iii) Criar instâncias dinamicamente usando ActivatorUtilities
https://www.itsvse.com/thread-9488-1-1.html

ASP.NET Núcleo (2) Reiniciar a aplicação por código
https://www.itsvse.com/thread-9480-1-1.html

ASP.NET Core (1) usa cache Redis
https://www.itsvse.com/thread-9393-1-1.html
Comece anexando o endereço open source ASP.NET Core do GitHub

O login do hiperlink está visível.
O login do hiperlink está visível.


asp.net Endereço do código-fonte principal
https://www.itsvse.com/thread-9394-1-1.html


Após criar um novo projeto ASP.NET Core 3.1, o código do programa é o seguinte:

Aprofundamos o código de entrada combinado com o código-fonte do GitHub.

Código do Hospedeiro:O login do hiperlink está visível.

Método CreateDefaultBuilder

Aqui instanciamos um objeto HostBuilder, que herda do IHostBuilder, e adicionamos delegados definidos pelo sistema, como :appsettings.json, appsettings. {env. EnvironmentName}.json arquivo de configuração, que eventualmente retornará: interface IHostBuilder.

Código HostBuilder:O login do hiperlink está visível.

O método Build será eventualmente chamado.


Build pública IHost()
{
    se (_hostBuilt)
    {
        lançar um novo InvalidOperationException(SR. BuildCalled);
    }
    _hostBuilt = verdadeiro;

    BuildHostConfiguration();
    CriarAmbienteDeHospedagem();
    CriarHostConstrutorContexto();
    BuildAppConfiguration();
    CreateServiceProvider();

    retorno _appServices.ReceberRequisitoServiço<IHost>();
}
Método BuildHostConfiguration

_hostConfiguration privada de Iconfiguração;
IConfigurationBuilder configBuilder = novo ConfigurationBuilder()
Chame o delegado para adicionar configuração em sua vez

Método CreateHostingEnvironment

privado HostingEnvironment _hostingEnvironment;
_hostingEnvironment = novo Ambiente de Hospedagem()
{
    NomeAplicação = _hostConfiguration[PadrãoHostPadrão.ChaveAplicação],
    NomeAmbiente = _hostConfiguration[HostDefaults.EnvironmentKey] ?? Ambientes.Produção,
    ContentRootPath = ResolveContentRootPath(_hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory),
};
Método CreateHostBuilderContext

privado HostBuilderContext _hostBuilderContext;
_hostBuilderContext = novo HostBuilderContext(Properties)
{
    HostingEnvironment = _hostingEnvironment,
    Configuração = _hostConfiguration
};
Método BuildAppConfiguration

Integre novamente as informações de configuração

IConfigurationBuilder configBuilder = novo ConfigurationBuilder()
                . SetBasePath(_hostingEnvironment.ContentRootPath)
                . AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true);
_appConfiguration = configBuilder.Build();
            _hostBuilderContext.Configuração = _appConfiguration;
Método CreateServiceProvider

var services = nova ServiceCollection();
Registre um serviço, chame um delegado e adicione um serviço definido pelo usuário.

Método de extensão GenericHostBuilderExtensions

O login do hiperlink está visível.

Método de extensão ConfigureWebHost

Para registrar o GenericWebHostService como um serviço backend:


construtor. ConfigureServices((contexto, serviços) = > serviços. AddHostedService<GenericWebHostService>());
GenericWebHostService Código:O login do hiperlink está visível.


Tarefa pública assíncrona StartAsync(CancellationToken cancellationToken)
        {
            HostingEventSource.Log.HostStart();

            var serverAddressesFeature = Server.Features.Get<IServerAddressesFeature>();
            var endereços = servidorEndereçosFuncionalidade?. Endereços;
            se (endereços != null && !endereços. Endereços IsReadOnly & & Only. Contagem == 0)
            {
                var urls = Configuration[WebHostDefaults.ServerUrlsKey];
                if (!string. IsNullOrEmpty(urls))
                {
                    FuncionalidadeEndereçosDo Servidor!. PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);

                    Foreach (valor var em URLs. Split('; ', StringSplitOptions.RemoveEmptyNtries))
                    {
                        endereços. Somar (valor);
                    }
                }
            }

            SolicitarDelegar? aplicação = nulo;

            tente
            {
                var configure = Options.ConfigureApplication;

                if (configure == null)
                {
                    lançar um novo InvalidOperationException($"No application configured. Por favor, especifique uma aplicação via IWebHostBuilder.UseStartup, IWebHostBuilder.Configure ou especificando o assembly de inicialização via {nameof(WebHostDefaults.StartupAssemblyKey)} no configuração de hospedagem.");
                }

                var builder = ApplicationBuilderFactory.CreateBuilder(Server.Features);

                foreach (var filter em StartupFilters.Reverse())
                {
                    configure = filtro. Configure(configure);
                }

                configure(builder);

                Construir o pipeline de requisições
                aplicação = construtor. Build();
            }
            captura (exceção ex)
            {
                Logger.ApplicationError(ex);

                se (! Options.WebHostOptions.CaptureStartupErrors)
                {
                    arremesse;
                }

                var showDetailedErrors = HostingEnvironment.IsDevelopment() || Options.WebHostOptions.DetailedErrors;

                aplicação = ConstrutorPáginaErro.BuildPáginaAplicaçãoErro(AmbienteDeHospedagem.FornecedorRaiz do Conteúdo, Logger, mostrarErrosDetalhados, ex);
            }

            var httpApplication = new HostingApplication(application, Logger, DiagnosticListener, HttpContextFactory);

            await Server.StartAsync(httpApplication, cancellationToken);

            se (endereços != nulo)
            {
                Foreach (endereço var em endereços)
                {
                    LifetimeLogger.ListeningOnAddress(endereço);
                }
            }

            if (Logger.IsEnabled(LogLevel.Debug))
            {
                foreach (var assembly em Options.WebHostOptions.GetFinalHostingStartupAssemblies())
                {
                    Logger.StartupAssemblyLoaded(assembly);
                }
            }

            if (Options.HostingStartupExceptions != null)
            {
                foreach (var exception em Options.HostingStartupExceptions.InnerExceptions)
                {
                    Logger.HostingStartupAssemblyError(exception);
                }
            }
        }


var webhostBuilder = novo GenericWebHostBuilder(builder, webHostBuilderOptions);
O login do hiperlink está visível.

Método de extensão WebHostBuilderExtensions

Fornece um objeto startupType para chamadas IWebHostBuilder.

este IWebHostBuilder hostBuilder
if (hostBuilder é ISupportsStartup suportaStartup)
{
    return supportsStartup.UseStartup(startupType);
}
O login do hiperlink está visível.

GenericWebHostBuilder Método Privado GenericWebHostBuilder

Instanciar dinamicamente nosso objeto Startup:

Exemplo?? = AtivadorUtilitários.CreateInstance(novo HostServiceProvider(webHostBuilderContext), startupType);
Contexto. Propriedades[_startupKey] = instância;
Procure pelo método ConfigureServices

var configureServicesBuilder = StartupLoader.FindConfigureServicesDelegate(startupType, context. AnfitriãoAmbiente.NomeAmbiente);
                var configureServices = configureServicesBuilder.Build(instance);

ConfigureServicesBuilder estático interno FindConfigureServicesDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo startupType, string NomeAmbiente)
        {
            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);
Procure pelo método ConfigureContainer

var configureContainerBuilder = StartupLoader.FindConfigureContainerDelegate(startupType, context. AnfitriãoAmbiente.NomeAmbiente);

ConfigureContainerBuilder estático interno FindConfigureContainerDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo startupType, string NomeAmbiente)
        {
            var configureMethod = FindMethod(startupType, "Configure{0}Container", environmentName, typeof(void), required: false);
            return new ConfigureContainerBuilder(configureMethod);
        }
Procure pelo método Configure

configureBuilder = StartupLoader.FindConfigureDelegate(startupType, context. AnfitriãoAmbiente.NomeAmbiente);

ConfigureBuilder estático interno FindConfigureDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Tipo startupType, string environmentName)
{
    var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true)!;
    return new ConfigureBuilder(configureMethod);
}
Chamado pelo método Build do ConfigureBuilder, o código-fonte é o seguinte:

classe privada ConfigureBuilder
        {
            ConfigureBuilder público (MethodInfo configure)
            {
                MethodInfo = configure;
            }

            MethodInfo público MethodInfo { get; }

            Build de ação pública<IApplicationBuilder> (instância de objeto)
            {
                return (applicationBuilder) => Invoke(instance, applicationBuilder);
            }

            private void Invoke(instance de objeto, construtor IApplicationBuilder)
            {
                var serviceProvider = builder. Serviços de Aplicação;
                var parameterInfos = MethodInfo.GetParameters();
                var parameters = new object[parameterInfos.Length];
                para (var índice = 0; índice < parâmetro Infos.Length; index++)
                {
                    var parameterInfo = parameterInfos[index];
                    if (parameterInfo.ParameterType == typeof(IApplicationBuilder))
                    {
                        parâmetros[índice] = construtor;
                    }
                    senão
                    {
                        tente
                        {
                            parameters[index] = ServiceProvider.GetRequiredService(parameterInfo.ParameterType);
                        }
                        captura (exceção ex)
                        {
                            lançar um novo InvalidOperationException(
                                Resources.FormatMiddlewareFilter_ServiceResolutionFail(
                                    parameterInfo.ParameterType.NomeCompleto,
                                    parameterInfo.Name,
                                    MethodInfo.Name,
                                    MethodInfo.DeclaringType.FullName),
                                ex);
                        }
                    }
                }
                MethodInfo.Invoke(instância, parâmetros);
            }
        }
Método de execução

Endereço do método de extensão HostingAbstractionsHostExtensions:

O login do hiperlink está visível.


Eventualmente liga:

/// <summary>
        Executa uma aplicação e retorna uma Tarefa que só é concluída quando o token é acionado ou quando o desligamento é acionado.
        /// </summary>
        <param name="host">O <veja cref="IHost"/> para executar.</param>
        <param name="token">O token para acionar o desligamento.</param>
        <returns>O <veja cref="Task"/> que representa a operação assíncrona.</returns>
        Tarefa pública estática assíncrona RunAsync (este host IHost, token CancellationToken = padrão)
        {
            tente
            {
                Aguarde o anfitrião. StartAsync(token). ConfigureAwait (false);

                Aguarde o anfitrião. WaitForShutdownAsync(token). ConfigureAwait (false);
            }
            finalmente
            {
                if (host é IAsyncDisposable asyncDisposable)
                {
                    await asyncDisposable.DisposeAsync(). ConfigureAwait (false);
                }
                senão
                {
                    apresentador. Descartar();
                }

            }
        }
Anteriormente, quando eu estava construindo um serviço, eu me registrava no serviço IHost, e o código é o seguinte:

serviços. <IHost>AddSingleton(_ =>
            {
                retorne novo Internal.Host(_appServices,
                    _appServices.GetRequiredService<IHostApplicationLifetime>(),
                    _appServices.GetRequiredService<ILogger<Internal.Host>>(),
                    _appServices.GetRequiredService<IHostLifetime>(),
                    _appServices.GetRequiredService<IOptions<HostOptions>>());
            });
Método StartAsync

Endereço:O login do hiperlink está visível.

Task StartAsync async publico(CancellationToken cancellationToken = default)
        {
            _logger. Inicial();

            usando var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _applicationLifetime.ApplicationStopping);
            CancellationToken combinadoCancellationToken = combinadoCancellationTokenSource.Token;

            await _hostLifetime.WaitForStartAsync(combinedCancellationToken). ConfigureAwait (false);

            combinedCancellationToken.ThrowIfCancellationRequested();
            _hostedServices = Services.GetService<IEnumerable<IHostedService>>();

            foreach (IHostedService hostedService em _hostedServices)
            {
                // Fire IHostedService.Start
                await hostedService.StartAsync(combinedCancellationToken). ConfigureAwait (false);

                if (hostedService é BackgroundService backgroundService)
                {
                    _ = HandleBackgroundException(backgroundService);
                }
            }

            Fogo IHostAplicaçãoVidaVida. Iniciado
            _applicationLifetime.NotifyStarted();

            _logger. Iniciado();
        }
(Fim)




Anterior:Relatos de novatos tardios
Próximo:Erro do .NET Core no pacote de aplicações de processamento de falha do Linux
Postado em 2021-9-22 20:45:12 |
Aprenda a aprender...
Disclaimer:
Todo software, material de programação ou artigos publicados pela Code Farmer Network são apenas para fins de aprendizado e pesquisa; O conteúdo acima não deve ser usado para fins comerciais ou ilegais, caso contrário, os usuários terão todas as consequências. As informações deste site vêm da Internet, e disputas de direitos autorais não têm nada a ver com este site. Você deve deletar completamente o conteúdo acima do seu computador em até 24 horas após o download. Se você gosta do programa, por favor, apoie um software genuíno, compre o registro e obtenha serviços genuínos melhores. Se houver qualquer infração, por favor, entre em contato conosco por e-mail.

Mail To:help@itsvse.com