Generic Host, DI, Configuration and Logging

30.1 Generic Host in a VB Console App

Imports Microsoft.Extensions.Configuration
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Hosting
Imports Microsoft.Extensions.Logging
Imports Microsoft.Extensions.Options

Public Class SmtpOptions
    Public Property Host As String
    Public Property Port As Integer = 25
    Public Property From As String
End Class

Public Interface IEmailSender
    Function SendAsync([to] As String, subject As String, body As String) As Task
End Interface

Public Class SmtpEmailSender
    Implements IEmailSender
    Private ReadOnly _options As SmtpOptions
    Private ReadOnly _logger As ILogger(Of SmtpEmailSender)
    Public Sub New(options As IOptions(Of SmtpOptions), logger As ILogger(Of SmtpEmailSender))
        _options = options.Value
        _logger = logger
    End Sub
    Public Function SendAsync([to] As String, subject As String, body As String) As Task Implements IEmailSender.SendAsync
        _logger.LogInformation("Sending '{Subject}' to {To} via {Host}:{Port}", subject, [to], _options.Host, _options.Port)
        Return Task.CompletedTask
    End Function
End Class

Module Program
    Sub Main(args As String())
        Dim builder = Host.CreateApplic
…
// appsettings.json
{
  "Smtp": { "Host": "smtp.example.com", "Port": 587, "From": "noreply@example.com" },
  "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning" } },
  "ConnectionStrings": { "Shop": "Server=(localdb)\\MSSQLLocalDB;Database=Shop;Trusted_Connection=True" }
}

30.2 Dependency Injection Concepts

One instance for the app Configuration, caches, HttpClient factories One per scope (request/unit of work) DbContext, unit of work New every time Lightweight stateless services

Constructor injection is preferred. Avoid the service locator pattern. Don't inject scoped services into singletons (captive dependencies).

Create scopes manually in workers: Using scope = provider.CreateScope().

DI in WinForms/WPF: build the host in Sub Main, resolve the main form or window from the container, and pass services via constructors.

30.3 Configuration

Providers: JSON (appsettings.{Environment}.json), environment variables, command-line arguments, User Secrets (development), Azure Key Vault, INI, XML.

The options pattern: IOptions(Of T), IOptionsSnapshot(Of T), IOptionsMonitor(Of T) (reload on change). Validation: .ValidateDataAnnotations().ValidateOnStart()..NET Framework: App.config + ConfigurationManager, plus My.Settings for user settings.

30.4 Logging

ILogger(Of T) with structured logging (message templates {OrderId}), log levels (Trace → Critical), scopes (logger.BeginScope), providers (Console, Debug, EventLog, EventSource).

Third-party: Serilog (sinks: file, Seq, Elasticsearch), NLog. Use LoggerMessage.Define for high-performance logging.