Console host bootstrap¶
This operation composes a generic .NET host for console applications — configuration precedence, console logging, and (for the SAIF variant) environment client/DB connectivity — then runs the hosted console service through its Initialize/Execute/Finish lifecycle.
| Field | Value |
|---|---|
| Operation ID | OP-18 |
| Trigger | A console application calls BuildConsoleApp<TConsole>() or BuildSaifConsoleApp<TConsole>(), then runs the built host. |
| Inputs | TConsole — the hosted console type (implements IHostedService, typically via ConsoleBase/ConsoleAsyncBase); command-line args. |
| Outputs | A configured IHost whose IHostedService executes the console application's logic; the process exit code. |
| Primary components | IHostBuilderExtensions.BuildConsoleApp, .BuildSaifConsoleApp; ConsoleBase; ConsoleAsyncBase |
| Entry point | src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IHostBuilderExtensions.cs (L24–63) |
Steps¶
BuildConsoleApp: configuration sources added in order —appsettings.json(optional), environment variables, command line (ifargssupplied) — later sources override earlier ones (BR-SE-20) Register SingletonIHostedService → TConsole; configure logging withAddConfiguration("Logging")andAddConsole.BuildSaifConsoleAppadditionally delegates to Register secure environment client viaRegisterSecureEnvironmentClient(typeof(TConsole))(BR-SE-03), delegates to Register DB connection client viaRegisterDBConnectionClient()(BR-SE-04), and registers SingletonIConsoleLogService → ConsoleLogService.
Origin:
ConsoleLogService's console-logging behavior is implemented inConfigure console loggerandWrite console log entry(SAIF.NetCore.Logging); this step only registers the singleton type — construction and logging calls happen later, at first resolution and at each log call. 3.ConsoleAsyncBase's constructor capturesStartTime = DateTime.Nowand writes a header viaIConsoleLogService;Disposewrites a footer and disposes the log service. -EndTimeis a get-only property that returnsDateTime.Nowon every read rather than a timestamp captured once at run completion;RunningTime(EndTime - StartTime) is therefore the elapsed time since construction at the moment it is read, not a value frozen at a prior completion event. 4.ConsoleBase.StartAsyncreturnsTask.Run(() => Run(), cancellationToken), schedulingRunon the thread pool with the cancellation token forwarded toTask.Runitself (not observed insideRun).RuncallsInitialize→Execute→Finishsequentially with notry/finally, then setsEnvironment.ExitCode = ExitCode(BR-SE-21).ConsoleBase.Stop()is an empty no-op; it does not write the footer — footer logging and log-service disposal happen only viaConsoleAsyncBase.Dispose().
Process flow¶
This diagram shows host construction and the Run() lifecycle through assignment of Environment.ExitCode; it does not depict process termination, which is a separate host-lifetime concern outside this operation's scope.
flowchart TD
Start([BuildConsoleApp / BuildSaifConsoleApp called]) --> S1[Add configuration sources in precedence order]
S1 --> S2[Register IHostedService and console logging]
S2 --> S3{BuildSaifConsoleApp variant?}
S3 -->|Yes| S3a["Register secure environment client +<br>DB connection client + IConsoleLogService"]
S3 -->|No| S4[Host built]
S3a --> S4
S4 --> S5[StartAsync runs Initialize then Execute then Finish]
S5 --> S6["Environment.ExitCode = ExitCode<br>(host lifetime/process exit are separate)"]
S6 --> EndOk([Run completes with exit status assigned])
Failure and edge-case behavior¶
ConsoleAsyncBase.EndTimerecomputesDateTime.Nowon every property read instead of returning a captured completion time;RunningTimeread fromWriteFooter()duringDispose()reflects the elapsed time up to that read, which is effectively the time of disposal, not a separately captured "run ended" instant.Run()'s three steps are not wrapped intry/finally: ifInitialize()orExecute()throws,Finish()does not run andEnvironment.ExitCodeis never assigned fromExitCode— the exception instead propagates out through theTaskreturned byStartAsync. The final process exit code reflectsConsoleBase.ExitCodeonly whenRun()completes all three steps without an unhandled exception.
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with**could not be confirmed; treat as unknown until verified.
Sources¶
src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/IHostBuilderExtensions.cssrc/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/ConsoleBase.cssrc/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/ConsoleAsyncBase.cs