.Net Core Console&Generic HostBuilder

Posted 微笑刺客D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.Net Core Console&Generic HostBuilder相关的知识,希望对你有一定的参考价值。

前言

有时候想快速验证一些想法,新建一个控制台来弄,可控制台模板是轻量级的应用程序模板,不具备配置、日志、依赖注入等一些功能。


通用主机

在Asp.Net Core中有WebHostBuilder来提供DI,Configuratio,日志等功能,很是齐全,如果是在控制台中使用呢,或是使用的场景不单单是Web呢,比如测试项目,独立Job,桌面应用等,除了手动一个一个搭建外,也可以使用Generic HostBuilder,类似于WebHostBuilder,也提供了基础的功能,免于我们再去基建。

https://source.dot.net/#Microsoft.Extensions.Hosting/HostBuilder.cs,148

Generic HostBuilder是在.Net Core2.1时候提出的并被设计成能够在非Http模式和Http模式下都可以用。


安装Nuget包

Install-Package Microsoft.Extensions.Hosting

构建主机

开始使用Generic HostBuilder,可以手动实例化HostBuilder,

var hostBuilder = new HostBuilder();

或是调用Host中的扩展方法来完成创建。

var hostBuilder = Host.CreateDefaultBuilder(args)

实际上,扩展方法中是在手动实例化的基础上包装并做好了一些基础配置与服务注册,源码位置:

https://source.dot.net/#Microsoft.Extensions.Hosting/Host.cs,53

微软官网文档中也提及了CreateDefaultBuilder中完成的一些事情。

https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host#default-builder-settings


服务注册

Generic HostBuilder很是方便我们去使用DI,在HostBuilder尚未执行Build方法前,先注册一些服务到容器中,此处注册个简单服务。


以订单服务类作为示例,增加接口类与实现类。

public interface IOrderService

    void AutoCancel();


public class OrderService : IOrderService

    private readonly ILogger<OrderService> _logger;

    public OrderService(ILogger<OrderService> logger)
    
        _logger = logger;
    

    public void AutoCancel()
    
        _logger.LogInformation("Start AutoCancel");
        Console.WriteLine("Order canceled!");
        _logger.LogInformation("Finished AutoCancel");
    


注册到服务容器中,此处使用瞬时的生命周期。

var hostBuilder = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    
        services.AddTransient<IOrderService, OrderService>();
    );

实例化主机

调用HostBuilder的Build方法,将约定好的服务全部转换到服务容器中,完成主机实例化。

https://source.dot.net/#Microsoft.Extensions.Hosting/HostBuilder.cs,148

实例化的主机其实现的接口是IHost

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    
        services.AddTransient<IOrderService, OrderService>();
    )
    .Build();

运行主机

如想要长时间运行(像是后台Job,订阅服务处理等都行),可以执行扩展方法Run(),实际还是调用的IHost接口中的StartAsync方法。

https://source.dot.net/#Microsoft.Extensions.Hosting.Abstractions/HostingAbstractionsHostExtensions.cs,63

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    
        services.AddTransient<IOrderService, OrderService>();
    )
    .Build();

host.Run();

控制台运行起来,可以看到启动初始化的日志记录,与Web启动时日志相似。


服务获取

当主机实例化完毕后,如我们想直接获取服务,执行服务方法,完成一些功能,那可以无需Run,在构建主机完毕后就从主机中获取服务执行方法。

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    
        services.AddTransient<IOrderService, OrderService>();
    )
    .Build();

// host.Run();

using (var serviceScope = host.Services.CreateScope())

    var services = serviceScope.ServiceProvider;
    var orderService = services.GetRequiredService<IOrderService>();
    orderService.AutoCancel();

启动后,构造函数注入,日志记录等功能一应俱全,不用再做基建工作了。


参考

https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host


2023-04-08,望技术有成后能回来看见自己的脚步

.Net Core App - 命令行格式异常

我正在遵循这个指南: - https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?tabs=aspnetcore2x

当我尝试使用--console命令行参数运行.exe文件时收到以下错误消息: -

未处理的异常:System.FormatException:缺少switch'--console'的值。

这是我的Program类的Main方法。

 public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.Console()
                .CreateLogger();

            var isService = !(Debugger.IsAttached || args.Contains("--console"));

            var pathToContentRoot = Directory.GetCurrentDirectory();
            if (isService)
            {
                var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
                pathToContentRoot = Path.GetDirectoryName(pathToExe);
            }

            var host = WebHost.CreateDefaultBuilder(args)
                .UseContentRoot(pathToContentRoot)
                .UseStartup<Startup>()
                .Build();

            if (isService)
            {
                host.RunAsCustomService();
            }
            else
            {
                host.Run();
            }
        }

我已经确保我从文件夹路径运行命令行参数。

答案

ASP.NET Core配置系统不接受没有值的交换机。它希望能够从参数创建键值对,因此请务必不要转发此参数:

var webHostcArgs = args.Where(arg => arg != "--console").ToArray();
var host = WebHost.CreateDefaultBuilder(webHostcArgs)
…

以上是关于.Net Core Console&Generic HostBuilder的主要内容,如果未能解决你的问题,请参考以下文章

.net core 的 Console 输出乱码问题

.net core 的 Console 输出乱码问题

.net core 的 Console 输出乱码问题

JVM内存区域划分Eden SpaceSurvivor SpaceTenured Gen,Perm Gen解释

在.NET Core console application中使用User Secrets(用户机密)

[Asp.Net Core]Autofac多种注入