Generic-Host 快速使用指南


.NETCORE 中的 Generic Host

本文以自己在工作中學習和使用.net core generic-host 作一個總結。

前言

在創建的ASPNETCORE項目中,我們可以在Main()中看見,我們通過IWebHostBuild創建了一個IWebHost,而微軟提供了WebHost.CreateDefaultBuilder(args)來幫助我們更輕松得創建WebHost

常常我們的需求不需要創建Web項目,比如后台任務,那么我們如何像使用AspNetCore一樣創建控制台項目。

如何在控制台程序中創建主機

  1. 通過dotnet new console 創建一個控制台項目
  2. 通過Nuget添加以下包
    • Microsoft.Extensions.Hosting

首先,我們看下IHostBuilder接口里的方法

public interface IHostBuilder
{
    IHost Build();

    IHostBuilder ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate);

    IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate);

    IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate);

    IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate);
    
    IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);
}

  • ConfigureAppConfiguration() 可以配置應用的一些配置,如環境變量等等
  • ConfigureContainer() & UseServiceProviderFactory() 可以配置替換默認的依賴注入的組件,比如替換成Autofac
  • ConfigureHostConfiguration() 可以配置IConfiguration
  • ConfigureServices() 可以注入服務

接下去,通過以下代碼,我們可以構建一個簡單的主機。

static void Main(string[] args)
{
    CreateDefaultHost(args).Build().Run();
}

static IHostBuilder CreateDefaultHost(string[] args) => new HostBuilder()
    .ConfigureHostConfiguration(builder =>
    {
        //todo
    })
    .ConfigureAppConfiguration((ctx, builder) =>
    {
        builder
            .SetBasePath(AppContext.BaseDirectory)
            .AddJsonFile("appsettings.json", true, true)
            .AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", true, true)
            .AddEnvironmentVariables()
            ;
    })
    .ConfigureServices((ctx, services) =>
    {
        services.AddLogging();
        services.AddHostedService<CustomHostService>();
    })
    .UseConsoleLifetime()
    ;


public class CustomHostService: IHostedService
{

    private ILogger _logger;
    private Task _executingTask;

    public Task StartAsync(...)
    {
        _logger.LogInformation($"{nameof(CustomHostService):}start");

        _executingTask = ExecuteAsync(...);
        if(_executingTask.IsCompleted){
            return _executingTask;
        }
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
    }

    public Task ExecuteAsync(...)
    {
        _logger.LogInformation($"{nameof(CustomHostService):executing}")
        return Task.Delay(5000);
    }

}

如上,我們自定義的 CustomHostService 需要實現 IHostedService接口,當然,我們可以直接繼承 BackgoundService 類。

在實現了 IHostedService 接口后,我們通過 services.AddHostedService<>() 進行注入,或者通過 service.AddTransient<IHostedService,THostedService>() 進入注入。

啟動以上項目,我們發現,我們的程序默認的Hosting Environment一直是Production,那么如何修改呢 ??

配置環境變量

在AspNetCore項目中,我們可以通過設置環境變量ASPNETCORE_ENVIRONMENT的值來指定主機環境變量的。而在Generic Host 中暫時沒有這一項配置。

如果查看IHostBuilder的擴展,我們會發現以下方法:


new HostBuilder()
    .UseContentRoot(...)
    .UseEnvironment(...)
    ...

查看源代碼后,我們可以通過ConfigureHostConfiguration()方法將這些配置配置到主機中。

現在我們假設我們以DOTNETCORE_ENVIRONMENT來指定GenericHost的環境。

new HostBuilder().ConfigureHostConfiguration(builder =>
    {
        builder.AddInMemoryCollection(new Dictionary<string, string>
        {
            [HostDefaults.EnvironmentKey] = Environment.GetEnvironmentVariable("DOTNETCORE_ENVIRONMENT"),
        })
        // Nuget:Microsoft.Extensions.Configuration.CommandLine
        //.AddCommandLine(args) 
        ;
    })
    
    //...

現在讓我們打開命令行測試下。設置完成環境變量后我們通過dotnet run 啟動程序。查看輸出,Host Environment 變成為 Stage

# 設置環境變量
$env:DOTNETCORE_ENVIRONMENT='Stage'
# 查看環境變量
$env:DOTNETCORE_ENVIRONMENT

當然我們也可以通過 commandline 的參數來設置啟動的環境變量等值。

Install-Package Microsoft.Extensions.Configuration.CommandLine

ConfigureHostConfiguration()中使用.AddCommandLine(args)來指定參數。

現在我們可以通過 dotnet run --environment=Development來指定dev環境了,此時我們發現我們終於成功加載appsettings.Development.json中的配置信息了。

使用Autofac來替代默認的 DI

簡單認識一下Autofac

一個第三方的依賴注入容器,相對Microsft.Extensions.DependencyInjection使用更加簡單方便。

集成到Host中

通過Nuget安裝以下兩個包

Install-Package Autofac

Install-Package Autofac.Extensions.DependencyInection

我們可以使用UseServiceProviderFactory()service.AddAutofac() 將默認的DI 替換成 Autofac;

使用ConfigureContainer<ContainerBuilder>()可以使用Autofac來注入服務;

//省略了非關鍵代碼
static IHostBuilder CreateDefaultHost(string[] args) => new HostBuilder()
//...略
    .ConfigureServices((ctx, services) =>
    {
        services.AddLogging(x=>{x.AddConsole();});

        services.AddAutofac();
    })
    .ConfigureContainer<ContainerBuilder>(builder => 
    {
        builder.RegisterType<CustomHostService>()
        .As<IHostedService>()
        .InstancePerDependency();
    })          
    .UseServiceProviderFactory<ContainerBuilder>(new AutofacServiceProviderFactory())
//...略

總結

個人認為出現GenericHost解決的幾個痛點,相對AspNetCore中的管道機制,控制台程序如果不依靠GenericHost來管理Di,想進行大量Microsoft.Extensions包的集成會非常困難。通過IHostedService,可以方便的進行服務的托管。

源碼: https://github.com/missxueo/docs-generic-host


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM