Преглед:
Започнете, като прикачите ASP.NET Core GitHub open source адреса
Входът към хиперлинк е видим.
Входът към хиперлинк е видим.
След създаването на нов проект 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. Започнато(); } (Край)
|