Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 59583|Відповідь: 1

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

[Копіювати посилання]
Опубліковано 2021-3-24 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 Ядро (2) Перезапуск додатку за кодом
https://www.itsvse.com/thread-9480-1-1.html

ASP.NET Core (1) використовує кешування Redis
https://www.itsvse.com/thread-9393-1-1.html
Почніть з приєднання відкритої адреси GitHub ASP.NET 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

приватне середовище хостингу _hostingEnvironment;
_hostingEnvironment = новий HostingEnvironment()
{
    ApplicationName = _hostConfiguration[HostDefaults.ApplicationKey],
    EnvironmentName = _hostConfiguration[HostDefaults.EnvironmentKey] ?? Середовища. Виробництво,
    ContentRootPath = ResolveContentRootPath(_hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory),
};
Метод CreateHostBuilderContext

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

Інтегруйте інформацію про конфігурацію знову

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

var services = новий ServiceCollection();
Зареєструйте сервіс, викликайте делегата та додайте сервіс, визначений користувачем.

Метод розширення GenericHostBuilderExtensions

Вхід за гіперпосиланням видно.

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 та адреси. Кількість == 0)
            {
                var urls = Configuration[WebHostDefaults.ServerUrlsKey];
                if (!string. IsNullOrEmpty(urls))
                {
                    serverAddressesFeature!. PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);

                    foreach (значення var у URL. Спліт('; ', StringSplitOptions.RemoveEmptyEntries))
                    {
                        адреси. Add(value);
                    }
                }
            }

            RequestDelegate? застосування = 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 у StartupFilters.Reverse())
                {
                    configure = filter. Configure(configure);
                }

                configure(builder);

                Побудуйте конвеєр запитів
                application = конструктор. 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);

            await Server.StartAsync(httpApplication, cancellationToken);

            якщо (адреси != 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 = новий GenericWebHostBuilder(builder, webHostBuilderOptions);
Вхід за гіперпосиланням видно.

Метод розширення WebHostBuilderExtensions

Надає об'єкт startupType для викликів IWebHostBuilder.

цей IWebHostBuilder hostBuilder
if (hostBuilder — ISupportsStartup підтримує Startup)
{
    return supportsStartup.UseStartup(startupType);
}
Вхід за гіперпосиланням видно.

GenericWebHostBuilder Приватний метод GenericWebHostBuilder

Динамічно інстанціюйте наш об'єкт Start:

Інстанс ?? = 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)] Тип 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. ApplicationServices;
                var parameterInfos = MethodInfo.GetParameters();
                var parameters = новий об'єкт[parameterInfos.Length];
                для (індекс VAR = 0; index < parameterInfos.Length; index++)
                {
                    var parameterInfo = parameterInfos[index];
                    якщо (parameterInfo.ParameterType == typeof(IApplicationBuilder))
                    {
                        параметри[індекс] = будівельник;
                    }
                    інше
                    {
                        спробуйте
                        {
                            parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType);
                        }
                        catch (виняток, наприклад)
                        {
                            throw new InvalidOperationException(
                                Resources.FormatMiddlewareFilter_ServiceResolutionFail(
                                    parameterInfo.ParameterType.FullName,
                                    parameterInfo.Name,
                                    MethodInfo.Name,
                                    MethodInfo.DeclaringType.FullName),
                                ex);
                        }
                    }
                }
                MethodInfo.Invoke (екземпляр, параметри);
            }
        }
Метод запуску

Адреса методу розширення HostingAbstractionsHostExtensions:

Вхід за гіперпосиланням видно.


Зрештою дзвонить:

/// <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)
                {
                    waitit asyncDisposable.DisposeAsync(). ConfigureAwait(хибно);
                }
                інше
                {
                    Господар. Позбавлятися();
                }

            }
        }
Раніше, коли я створював сервіс, я реєструвався на сервіс 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
Опубліковано 2021-9-22 20:45:12 |
Навчися вчитися...
Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com