Эта статья является зеркальной статьёй машинного перевода, пожалуйста, нажмите здесь, чтобы перейти к оригиналу.

Вид: 59583|Ответ: 1

[Источник] ASP.NET Core (7) Глубокий анализ исходного кода фреймворка

[Скопировать ссылку]
Опубликовано 24.03.2021 13:43:28 | | |
Обзор:

ASP.NET Core (VI) DI вручную получает метод введения объектов
https://www.itsvse.com/thread-9595-1-1.html

ASP.NET Core (пять) основана на распределённых транзакциях с CAP
https://www.itsvse.com/thread-9593-1-1.html

ASP.NET Фильтр Core(4) унифицированная валидация модели ModelState
https://www.itsvse.com/thread-9589-1-1.html

ASP.NET Ядро (iii) Динамическое создание экземпляров с помощью ActivatorUtilities
https://www.itsvse.com/thread-9488-1-1.html

ASP.NET Core (2) Перезапустить приложение по коду
https://www.itsvse.com/thread-9480-1-1.html

ASP.NET Core (1) использует кэширование Redis
https://www.itsvse.com/thread-9393-1-1.html
Начните с прикрепления открытого исходного ASP.NET адреса GitHub Core

Вход по гиперссылке виден.
Вход по гиперссылке виден.


asp.net Адрес основного исходного кода
https://www.itsvse.com/thread-9394-1-1.html


После создания нового проекта ASP.NET Core 3.1 код программы выглядит следующим образом:

Мы глубоко изучили код, совмещённый с исходным кодом GitHub.

Код хоста:Вход по гиперссылке виден.

Метод CreateDefaultBuilder

Здесь мы создаём объект HostBuilder, который наследует от IHostBuilder, и добавляем системные делегаты, такие как :appsettings.json, appsettings. {env. EnvironmentName}.json конфигурационный файл, который в конечном итоге вернёт: интерфейс IHostBuilder.

Код HostBuilder:Вход по гиперссылке виден.

В конечном итоге будет вызван метод Build.


Публичный IHost Build()
{
    если (_hostBuilt)
    {
        throw new InvalidOperationException(SR. BuildCalled);
    }
    _hostBuilt = истинно;

    BuildHostConfiguration();
    СоздатьХостингОкружение();
    CreateHostBuilderContext();
    BuildAppConfiguration();
    CreateServiceProvider();

    возврат _appServices.GetRequiredService<IHost>();
}
Метод BuildHostConfiguration

частный IConfiguration _hostConfiguration;
IConfigurationBuilder configBuilder = новый ConfigurationBuilder()
Вызовите делегата для добавления конфигурации

Метод CreateHostingEnvironment

Private HostingEnvironment _hostingEnvironment;
_hostingEnvironment = новый HostingEnvironment()
{
    ApplicationName = _hostConfiguration[HostDefaults.ApplicationKey],
    EnvironmentName = _hostConfiguration[HostDefaults.EnvironmentKey] ?? Окружения. Производство,
    ContentRootPath = ResolveContentRootPath(_hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory),
};
CreateHostBuilderContext method

приватный HostBuilderContext _hostBuilderContext;
_hostBuilderContext = новый HostBuilderContext(Properties)
{
    HostingEnvironment = _hostingEnvironment,
    Конфигурация = _hostConfiguration
};
Метод BuildAppConfiguration

Интегрируйте конфигурационную информацию снова

IConfigurationBuilder configBuilder = новый ConfigurationBuilder()
                . SetBasePath(_hostingEnvironment.ContentRootPath)
                . AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true);
_appConfiguration = configBuilder.Build();
            _hostBuilderContext.Конфигурация = _appConfiguration;
Метод CreateServiceProvider

var services = новый ServiceCollection();
Зарегистрируйте сервис, вызовите делегата и добавьте пользовательский сервис.

Метод расширения GenerricHostBuilderExtensions

Вход по гиперссылке виден.

ConfigureWebHost extension method

Для регистрации GenericWebHostService как бэкенд-сервиса:


Строитель. ConfigureServices((context, services) => services. <GenericWebHostService>AddHostedService());
Код GenericWebHostService:Вход по гиперссылке виден.


public async Task StartAsync(CancellationToken cancellationToken)
        {
            HostingEventSource.Log.HostStart();

            var serverAddressesFeature = Server.Features.Get<IServerAddressesFeature>();
            var addresses = serverAddressesFeature?. Адреса;
            если (адреса != null && !адреса. IsReadOnly и адреса. Count == 0)
            {
                var urls = Configuration[WebHostDefaults.ServerUrlsKey];
                если (!string. IsNullOrEmpty(urls))
                {
                    serverAddressesFeature!. PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);

                    foreach (значение var в URL. Split('; ', StringSplitOptions.RedeleEmptyEntries))
                    {
                        адреса. Add(value);
                    }
                }
            }

            ЗапроситьДелегировать? применение = null;

            Попробуй
            {
                var configure = Options.ConfigureApplication;

                if (configure == null)
                {
                    throw new InvalidOperationException($"No application configurened. Пожалуйста, укажите приложение через IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, или укажите ассембл запуска через {nameof(WebHostDefaults.StartupAssemblyKey)} в разделе конфигурация веб-хоста.»);
                }

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

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

                configure(builder);

                Постройте конвейер запросов
                приложение = конструктор. Build();
            }
            catch (исключение, например)
            {
                Logger.ApplicationError(ex);

                если (! Options.WebHostOptions.CaptureStartupErrors)
                {
                    бросать;
                }

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

                application = ErrorPageBuilder.BuildErrorPageApplication(HostingEnvironment.ContentRootFileProvider, Logger, showDetailedErrors, ex);
            }

            var httpApplication = новый HostingApplication (application, Logger, DiagnosticListener, HttpContextFactory);

            ожидать Server.StartAsync(httpApplication, cancellationToken);

            if (адреса != null)
            {
                foreach (VAR адрес в адресах)
                {
                    LifetimeLogger.ListeningOnAddress(адрес);
                }
            }

            if (Logger.IsEnabled(LogLevel.Debug))
            {
                foreach (var assembly in Options.WebHostOptions.GetFinalHostingStartupAssemblies())
                {
                    Logger.StartupAssemblyLoaded(ассемблер);
                }
            }

            if (Options.HostingStartupExceptions != null)
            {
                foreach (var exception in Options.HostingStartupExceptions.InnerExceptions)
                {
                    Logger.HostingStartupAssemblyError(исключение);
                }
            }
        }


var webhostBuilder = новый GenerricWebHostBuilder(builder, webHostBuilderOptions);
Вход по гиперссылке виден.

Метод расширения WebHostBuilderExtensions

Предоставляет объект startupType для вызовов IWebHostBuilder.

этот IWebHostBuilder hostBuilder
if (hostBuilder is ISupportsStartup supportsStartup)
{
    return supportsStartup.UseStartup(startupType);
}
Вход по гиперссылке виден.

GenericWebHostBuilder Private Method GenericWebHostBuilder

Динамически инстанцируйте наш объект Startup:

Пример ?? = ActivatorUtilities.CreateInstance(новый HostServiceProvider(webHostBuilderContext), startupType);
Контекст. Свойства[_startupKey] = экземпляр;
Ищите метод ConfigureServices

var configureServicesBuilder = StartupLoader.FindConfigureServicesDelegate(startupType, context. HostingEnvironment.EnvironmentName);
                var configureServices = configureServicesBuilder.Build(instance);

внутренний статический ConfigureServicesBuilder FindConfigureServicesDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType, string environmentName)
        {
            var servicesMethod = FindMethod(startupType, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false)
                ?? FindMethod(startupType, "Configure{0}Services", environmentName, typeof(void), required: false);
            вернуть новый ConfigureServicesBuilder(servicesMethod);
Ищите метод ConfigureContainer

var configureContainerBuilder = StartupLoader.FindConfigureContainerDelegate(startupType, context. HostingEnvironment.EnvironmentName);

внутренний статический ConfigureContainerBuilder FindConfigureContainerDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType, строка environmentName)
        {
            var configureMethod = FindMethod(startupType, "Configure{0}Container", environmentName, typeof(void), required: false);
            вернуть новый ConfigureContainerBuilder(configureMethod);
        }
Ищите метод Configure

configureBuilder = StartupLoader.FindConfigureDelegate(startupType, context. HostingEnvironment.EnvironmentName);

внутренний статический ConfigureBuilder FindConfigureDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType, string environmentName)
{
    var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true)!;
    вернуть новый ConfigureBuilder(configureMethod);
}
Исходный код вызывается методом ConfigureBuilder Build, а исходный код выглядит следующим образом:

Частный класс ConfigureBuilder
        {
            public ConfigureBuilder(MethodInfo configure)
            {
                MethodInfo = конфигурировать;
            }

            public MethodInfo MethodInfo { get; }

            <IApplicationBuilder> Публичный Action Build (экземпляр объекта)
            {
                return (applicationBuilder) => Invoke (экземпляр, applicationBuilder);
            }

            private void Invoke (object instance, IApplicationBuilder builder)
            {
                var serviceProvider = builder. ApplicationsServices;
                var parameterInfos = MethodInfo.GetParameters();
                var parameters = новый объект[parameterInfos.Length];
                для (индекс var = 0; index < parameterInfos.Length; index++)
                {
                    var parameterInfo = parameterInfos[index];
                    if (parameterInfo.ParameterType == typeof(IApplicationBuilder))
                    {
                        parameters[index] = конструктор;
                    }
                    Другое
                    {
                        Попробуй
                        {
                            parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType);
                        }
                        catch (исключение, например)
                        {
                            throw new InvalidOperationException(
                                Resources.FormatMiddlewareFilter_ServiceResolutionFail(
                                    parameterInfo.ParameterType.FullName,
                                    parameterInfo.Name,
                                    MethodInfo.Name,
                                    MethodInfo.DeclamingType.FullName),
                                ex);
                        }
                    }
                }
                MethodInfo.Invoke (экземпляр, параметры);
            }
        }
Метод запуска

Адрес метода расширения HostExtensions:

Вход по гиперссылке виден.


В конце концов звонит:

/// <summary>
        Запускает приложение и возвращает задачу, которая завершается только при срабатывании токена или отключении.
        /// </summary>
        <param name="host">The <see cref="IHost"/> для запуска</param>.
        <param name="token">Токен для запуска выключения</param>.
        <returns><см. cref="Задача"/> представляет асинхронную операцию.</returns>
        публичный статический асинхронный Task RunAsync (этот хост IHost, токен CancellationToken = по умолчанию)
        {
            Попробуй
            {
                Ждите хозяина. StartAsync(токен). ConfigureAwait (ложно);

                Ждите хозяина. WaitForShutdownAsync(token). ConfigureAwait (ложно);
            }
            наконец-то
            {
                если (хост — IAsyncDisposable asyncDisposable)
                {
                    ждать asyncDisposable.DisposeAsync(). ConfigureAwait (ложно);
                }
                Другое
                {
                    Ведущий. Dispose();
                }

            }
        }
Раньше, когда я создавал сервис, я регистрировался на сервис IHost, и код был следующим:

Услуги. <IHost>AddSingleton(_ =>
            {
                Вернуть новый Internal.Host(_appServices,
                    _appServices.GetRequiredService<IHostApplicationLifetime>(),
                    _appServices.GetRequiredService<ILogger<Internal.Host>>(),
                    _appServices.GetRequiredService<IHostLifetime>(),
                    _appServices.GetRequiredService<<HostOptions>IOptions>());
            });
Метод StartAsync

Адрес:Вход по гиперссылке виден.

public async Task StartAsync(CancellationToken cancellationToken = по умолчанию)
        {
            _logger. Starting();

            используя var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _applicationLifetime.ApplicationStopping);
            CancellationToken combinedCancellationToken = combinedCancellationTokenSource.Token;

            Ожидайте _hostLifetime.WaitForStartAsync(combinedCancellationToken). ConfigureAwait (ложно);

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

            foreach (IHostedService hostedService в _hostedServices)
            {
                // Fire IHostedService.Start
                waitit hostedService.StartAsync(combinedCancellationToken). ConfigureAwait (ложно);

                если (hostedService — это BackgroundService backgroundService)
                {
                    _ = HandleBackgroundException(backgroundService);
                }
            }

            Fire IHostApplicationLife.Started
            _applicationLifetime.NotifyStarted();

            _logger. Start();
        }
(Конец)




Предыдущий:Поздние новостные сообщения
Следующий:Ошибка .NET Core в пакете приложений для обработки сбоев Linux
Опубликовано 22.09.2021 20:45:12 |
Научись учиться...
Отказ:
Всё программное обеспечение, программные материалы или статьи, публикуемые Code Farmer Network, предназначены исключительно для учебных и исследовательских целей; Вышеуказанный контент не должен использоваться в коммерческих или незаконных целях, иначе пользователи несут все последствия. Информация на этом сайте взята из Интернета, и споры по авторским правам не имеют отношения к этому сайту. Вы должны полностью удалить вышеуказанный контент с компьютера в течение 24 часов после загрузки. Если вам нравится программа, пожалуйста, поддержите подлинное программное обеспечение, купите регистрацию и получите лучшие подлинные услуги. Если есть нарушение, пожалуйста, свяжитесь с нами по электронной почте.

Mail To:help@itsvse.com