Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 59583|Отговор: 1

[Източник] ASP.NET Ядро (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 Ядро (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 Core GitHub open source адреса

Входът към хиперлинк е видим.
Входът към хиперлинк е видим.


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();
    СъздавайХостингСреда();
    Създай HostBuilderContext();
    BuildAppConfiguration();
    CreateServiceProvider();

    return _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

частен 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 = new 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 адреси = 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(стойност);
                    }
                }
            }

            RequestDelegate? приложение = null;

            Опитай
            {
                var configure = Options.ConfigureApplication;

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

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

                foreach (var филтър в StartupFilters.Reverse())
                {
                    configure = filter. Configure(configure);
                }

                конфигуриране (строител);

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

                ако (! Options.WebHostOptions.CaptureStartupErrors)
                {
                    хвърляне;
                }

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

                application = ErrorPageBuilder.BuildErrorPageApplication(HostingEnvironment.ContentRootFileProvider, Logger, showDetailedErrors, напр);
            }

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

            wait Server.StartAsync(httpApplication, cancellationToken);

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

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

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


var webhostBuilder = нов GenericWebHostBuilder(builder, webHostBuilderOptions);
Входът към хиперлинк е видим.

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

Предоставя обект startupType за IWebHostBuilder извиквания.

този IWebHostBuilder hostBuilder
ако (hostBuilder е ISupportsStartup supportsStartup)
{
    return supportsStartup.UseStartup(startupType);
}
Входът към хиперлинк е видим.

GenericWebHostBuilder Частен метод 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)] Тип startupType, низ environmentName)
        {
            var configureMethod = FindMethod(startupType, "Configure{0}Container", environmentName, typeof(void), required: false);
            return new ConfigureContainerBuilder(configureMethod);
        }
Потърсете метода Configure

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

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

частен клас ConfigureBuilder
        {
            public ConfigureBuilder(MethodInfo configure)
            {
                MethodInfo = конфигуриране;
            }

            public MethodInfo MethodInfo { get; }

            Публичен<IApplicationBuilder> Action Build (инстанция на обект)
            {
                return (applicationBuilder) => Invoke(instance, 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.DecordiningType.FullName),
                                ex);
                        }
                    }
                }
                MethodInfo.Invoke (instance, parameters);
            }
        }
Метод на изпълнение

Адрес на метода на разширението HostAbstractionsHostExtensions:

Входът към хиперлинк е видим.


В крайна сметка се обажда:

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

                Очаквайте водещия. WaitForShutdownAsync(token). ConfigureAwait(false);
            }
            Накрая
            {
                ако (хостът е IAsyncDisposable asyncDisposable)
                {
                    wait asyncDisposable.DisposeAsync(). ConfigureAwait(false);
                }
                Друго
                {
                    Домакин. 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(cancelToken, _applicationLifetime.ApplicationStopping);
            CancellationToken combinedCancellationToken = комбиниранCancellationTokenSource.Token;

            Чакайте _hostLifetime.WaitForStartAsync(combinedCancellationToken). ConfigureAwait(false);

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

            foreach (IHostedService hostedService през _hostedServices г.)
            {
                // Fire IHostedService.Start
                waitit hostedService.StartAsync(combinedCancellationToken). ConfigureAwait(false);

                ако (hostedService е BackgroundService backgroundService)
                {
                    _ = HandleBackgroundException(backgroundService);
                }
            }

            // Fire IHostApplicationLifetime.Started
            _applicationLifetime.NotifyStarted();

            _logger. Започнато();
        }
(Край)




Предишен:Доклади за късни новодошли
Следващ:.NET Core грешка в Linux пакет приложения за обработка на повреди
Публикувано на 22.09.2021 20:45:12 |
Научи се да учиш...
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com