이 글은 기계 번역의 미러 문서이며, 원본 기사로 바로 이동하려면 여기를 클릭해 주세요.

보기: 59583|회답: 1

[출처] ASP.NET 핵심 (7) 프레임워크 소스 코드에 대한 심층 분석

[링크 복사]
2021-3-24 13:43:28에 게시됨 | | |
복습:

ASP.NET 코어(VI) DI는 객체 주입 방식을 수동으로 획득합니다
https://www.itsvse.com/thread-9595-1-1.html

ASP.NET 코어(다섯 개)는 CAP 분산 트랜잭션을 기반으로 합니다
https://www.itsvse.com/thread-9593-1-1.html

ASP.NET 코어(4) 필터 통합 모델스테이트 모델 검증
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 코어(1)는 Redis 캐싱을 사용합니다
https://www.itsvse.com/thread-9393-1-1.html
먼저 ASP.NET Core GitHub 오픈 소스 주소를 첨부하세요

하이퍼링크 로그인이 보입니다.
하이퍼링크 로그인이 보입니다.


asp.net 코어 소스 코드 주소
https://www.itsvse.com/thread-9394-1-1.html


Core 3.1 ASP.NET 새 프로젝트를 생성한 후, 프로그램 코드는 다음과 같습니다:

우리는 GitHub 소스 코드와 결합된 진입 코드를 깊이 파고들었습니다.

호스트 코드:하이퍼링크 로그인이 보입니다.

CreateDefaultBuilder 메서드

여기서는 IHostBuilder에서 상속받은 HostBuilder 객체를 인스턴스화하고, :appsettings.json, appsettings 같은 시스템 정의 대리자를 추가합니다. {env. EnvironmentName}.json 구성 파일이며, 결국 IHostBuilder 인터페이스를 반환할 예정입니다.

HostBuilder 코드:하이퍼링크 로그인이 보입니다.

빌드 메서드는 결국 호출될 것입니다.


공개 IHost 빌드()
{
    만약 (_hostBuilt)
    {
        새로운 InvalidOperationException(SR. BuildCalled);
    }
    _hostBuilt = 참;

    BuildHostConfiguration();
    호스팅 환경 만들기();
    CreateHostBuilderContext();
    BuildAppConfiguration();
    CreateServiceProvider();

    return _appServices.GetRequiredService<IHost>();
}
BuildHostConfiguration 메서드

개인 아이콘 피규_hostConfiguration;
IConfigurationBuilder configBuilder = new ConfigurationBuilder()
대리인에게 전화해서 차례로 구성을 추가하세요

CreateHostingEnvironment 메서드

private HostingEnvironment _hostingEnvironment;
_hostingEnvironment = 새로운 호스팅환경()
{
    ApplicationName = _hostConfiguration[HostDefaults.ApplicationKey],
    EnvironmentName = _hostConfiguration[HostDefaults.EnvironmentKey] ?? 환경.프로덕션,
    ContentRootPath = ResolveContentRootPath(_hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory),
};
CreateHostBuilderContext 메서드

private HostBuilderContext _hostBuilderContext;
_hostBuilderContext = new HostBuilderContext(Properties)
{
    HostingEnvironment = _hostingEnvironment,
    구성 = _hostConfiguration
};
BuildAppConfiguration 메서드

구성 정보를 다시 통합하세요

IConfigurationBuilder configBuilder = new ConfigurationBuilder()
                . SetBasePath(_hostingEnvironment.ContentRootPath)
                . AddConfiguration(_hostConfiguration, shouldDisposeConfiguration: true);
_appConfiguration = configBuilder.Build();
            _hostBuilderContext.Configuration = _appConfiguration;
CreateServiceProvider 메서드

var services = new ServiceCollection();
서비스를 등록하고, delegate를 호출한 뒤 사용자 정의 서비스를 추가하세요.

GenericHostBuilderExtensions 확장 방법

하이퍼링크 로그인이 보입니다.

ConfigureWebHost 확장 방법

GenericWebHostService를 백엔드 서비스로 등록하려면:


건축가. ConfigureServices((맥락, 서비스) => 서비스. AddHostedService<GenericWebHostService>());
일반 WebHostService 코드:하이퍼링크 로그인이 보입니다.


공개 비동기 작업 시작(CancellationToken cancellationToken)
        {
            HostingEventSource.Log.HostStart();

            var serverAddressesFeature = <IServerAddressesFeature>Server.Features.Get();
            var addresses = serverAddressesFeature?. 주소;
            만약 (addresses != null & !addresses. IsReadOnly & 주소. 카운트 == 0)
            {
                var urls = Configuration[WebHostDefaults.ServerUrlsKey];
                만약 (!string. IsNullOrEmpty(urls))
                {
                    서버주소기능!. PreferHostingUrls = WebHostUtilities.ParseBool(Configuration, WebHostDefaults.PreferHostingUrlsKey);

                    foreach(URL의 var 값. 스플릿('; ', StringSplitOptions.RemoveEmptyEntrys))
                    {
                        주소들. 더하기(가치);
                    }
                }
            }

            요청 위임? application = null;

            시도해
            {
                var configure = Options.ConfigureApplication;

                if (구성 == null)
                {
                    throw new InvalidOperationException($"No application configured. IWebHostBuilder.UseStartup, IWebHostBuilder.Configure, 또는 {nameof(WebHostDefaults.StartupAssemblyKey)}에서 시작 어셈블리를 지정하여 애플리케이션을 지정해 주세요. 웹 호스트 구성.");
                }

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

                foreach (StartupFilters.Reverse()의 var 필터)
                {
                    구성 = 필터. 구성(구성);
                }

                구성(건축가);

                요청 파이프라인을 구축하세요
                응용 = 건축가. 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 = new HostingApplication(application, Logger, DiagnosticListener, HttpContextFactory);

            wait, Server.StartAsync(httpApplication, cancellationToken);

            만약 (addresses != null)
            {
                foreach (주소 내 var 주소)
                {
                    LifetimeLogger.ListeningOnAddress(address);
                }
            }

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

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


var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions);
하이퍼링크 로그인이 보입니다.

WebHostBuilderExtensions 확장 메서드

IWebHostBuilder 호출을 위한 startupType 객체를 제공합니다.

이 IWebHostBuilder 호스트빌더
if(hostBuilder는 ISupportsStartup supportsStartup입니다)
{
    return supportsStartup.UseStartup(startupType);
}
하이퍼링크 로그인이 보입니다.

GenericWebHostBuilder 개인 방법 GenericWebHostBuilder

Startup 객체를 동적으로 인스턴스화하기:

인스턴스 ?? = ActivatorUtilities.CreateInstance(new HostServiceProvider(webHostBuilderContext), startupType);
맥락. 속성[_startupKey] = 인스턴스;
ConfigureServices 방법을 찾아보세요

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

internal static ConfigureServicesBuilder FindConfigureServicesDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupTypeType, string environmentName)
        {
            var servicesMethod = FindMethod(startupType, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false)
                ?? FindMethod(startupType, "Configure{0}Services", environmentName, typeof(void), 필수: false);
            새 ConfigureServicesBuilder(servicesMethod)를 반환;
ConfigureContainer 메서드를 찾아보세요

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

내부 정적 ConfigureContainerBuilder FindConfigureContainerDelegate([DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupTypeType, string environmentName)
        {
            var configureMethod = FindMethod(startupType, "Configure{0}Container", environmentName, typeof(void), required: false);
            return new ConfigureContainerBuilder(configureMethod);
        }
구성 메서드를 찾아보세요

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)를 반환;
}
ConfigureBuilder의 빌드 메서드로 호출된 소스 코드는 다음과 같습니다:

개인 클래스 ConfigureBuilder
        {
            public ConfigureBuilder(MethodInfo configure)
            {
                MethodInfo = configure;
            }

            public MethodInfo MethodInfo { get; }

            public Action<IApplicationBuilder> Build(객체 인스턴스)
            {
                return (applicationBuilder) => Invoke(instance, applicationBuilder);
            }

            private void Invoke(object instance, IApplicationBuilder builder)
            {
                var serviceProvider = builder. 애플리케이션서비스;
                var parameterInfos = MethodInfo.GetParameters();
                var parameters = new object[parameterInfos.Length];
                (var 지수 = 0; index < parameterInfos.Length; index++)
                {
                    var parameterInfo = parameterInfos[index];
                    if (parameterInfo.ParameterType == typeof(IApplicationBuilder))
                    {
                        매개변수[index] = 빌더;
                    }
                    그렇지 않으면
                    {
                        시도해
                        {
                            parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType);
                        }
                        catch (예외 예)
                        {
                            새로운 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="Task"/>.</returns>
        공개 정적 비동기 작업 RunAsync(이 IHost 호스트, CancellationToken 토큰 = 기본값)
        {
            시도해
            {
                주인을 기다려. StartAsync(token). ConfigureAwait(false);

                주인을 기다려. WaitForShutdownAsync(token). ConfigureAwait(false);
            }
            드디어
            {
                만약 (호스트는 IAsyncDisposable asyncDisposable)
                {
                    wait, asyncDisposable.DisposeAsync(). ConfigureAwait(false);
                }
                그렇지 않으면
                {
                    호스트. 처분();
                }

            }
        }
이전에 서비스를 구축할 때 IHost 서비스에 등록했는데, 코드는 다음과 같습니다:

서비스. AddSingleton<IHost>(_ =>
            {
                새 Internal.Host(_appServices,
                    _appServices.GetRequiredService<IHostApplicationLifetime>(),
                    _appServices.GetRequiredService<ILogger<Internal.Host>>(),
                    _appServices.GetRequiredService<IHostLifetime>(),
                    _appServices.GetRequiredService<IOptions<HostOptions>>());
            });
StartAsync 방법

주소:하이퍼링크 로그인이 보입니다.

공개 비동기 작업 시작(CancellationToken cancellationToken= default)
        {
            _logger. 스타팅();

            var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _applicationLifetime.ApplicationStopping);
            취소토큰 결합 취소토큰 = combinedcancellationTokenSource.Token;

            wait_hostLifetime.WaitForStartAsync(combinedCancellationToken). ConfigureAwait(false);

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

            foreach (IHostedService 호스팅된 서비스, _hostedServices)
            {
                화재 서비스. 시작
                await hostedService.StartAsync(combinedCancellationToken). ConfigureAwait(false);

                if (hostedService는 BackgroundService backgroundService입니다)
                {
                    _ = HandleBackgroundException(backgroundService);
                }
            }

            해고: IostApplicationLifetime. 시작됨.
            _applicationLifetime.NotifyStarted();

            _logger. 시작();
        }
(끝)




이전의:늦은 신참 보고서
다음:리눅스 실패 처리 애플리케이션 번들에서 .NET Core 오류
2021-9-22 20:45:12에 게시됨 |
배우기 시작해...
면책 조항:
Code Farmer Network에서 발행하는 모든 소프트웨어, 프로그래밍 자료 또는 기사는 학습 및 연구 목적으로만 사용됩니다; 위 내용은 상업적 또는 불법적인 목적으로 사용되지 않으며, 그렇지 않으면 모든 책임이 사용자에게 부담됩니다. 이 사이트의 정보는 인터넷에서 가져온 것이며, 저작권 분쟁은 이 사이트와는 관련이 없습니다. 위 내용은 다운로드 후 24시간 이내에 컴퓨터에서 완전히 삭제해야 합니다. 프로그램이 마음에 드신다면, 진짜 소프트웨어를 지원하고, 등록을 구매하며, 더 나은 진짜 서비스를 받아주세요. 침해가 있을 경우 이메일로 연락해 주시기 바랍니다.

Mail To:help@itsvse.com