我试图弄清楚如何使用主机构建器模式来运行控制台应用程序(而不是Windows服务)。目的是保持流程与 WebApi 相似,以保持开发实践相似。我见过使用 HostedService 或 BackGroundService 的示例,他们希望将其作为 Windows 服务运行。但是,如果我想运行一个简单的控制台应用程序,我在哪里指定我的入口点类和方法?从 hostbuilder.Build() 中,我可以看到 Run() 和 RunAsync() 方法。但我无法弄清楚它会执行什么?
我已经看到了其他示例,您可以在其中创建 servicecollection,然后使用 serviceprovider.GetService().SomeMethod() 来启动该过程。但这有点偏离我们想要做的事情。所以请建议如何指定启动过程。我们正在使用 3.1 .Net Core。
class Program
{
static async void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostBuilderContext, serviceCollection) => new Startup(hostBuilderContext.Configuration).ConfigureServices(serviceCollection))
.UseSerilog()
;
}
编辑: .NET 6 的更新如下 ↓
.NET 7 或 .NET 8 没有太大变化。
我将从默认的
worker
模板开始。它预装了必要的软件包。如果您已有项目,请安装 Microsoft.Extensions.Hosting
包。
dotnet new worker -n MyCli
然后打开
Program.cs
并构建主机。如果您不想采用托管服务路线,请删除 Worker
托管服务。
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// remove the hosted service
// services.AddHostedService<Worker>();
// register your services here.
});
}
建立你的逻辑:
internal class MyService
{
// you can also inject other services
private ILogger<MyService> _logger;
public MyService(ILogger<MyService> logger)
{
_logger = logger;
}
public void DoSomething()
{
_logger.LogInformation("Doing something");
}
}
然后在.ConfigureServices方法中注册类
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddTransient<MyService>();
});
现在您可以在
Main
方法中解析并调用它:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var myService = host.Services.GetRequiredService<MyService>();
myService.DoSomething();
}
使用 .NET 6,样板文件显着减少。我们可以将
Program.cs
重写为:
using Microsoft.Extensions.Hosting; // Requires NuGet package
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services => { services.AddTransient<MyService>(); })
.Build();
var my = host.Services.GetRequiredService<MyService>();
await my.ExecuteAsync();
class MyService
{
private readonly ILogger<MyService> _logger;
public MyService(ILogger<MyService> logger)
{
_logger = logger;
}
public async Task ExecuteAsync(CancellationToken stoppingToken = default)
{
_logger.LogInformation("Doing something");
}
}
基本上:
实例化您的主机构建器并配置您的服务等等。
为您的程序创建一个带有方法的类,并将该类注册为服务。
构建主机,创建作用域,获取类的实例,调用您的方法。
我的程序是我班级
MainAsync
中的方法ProgramAsync
。
class Program
{
static void Main(string[] args)
{
using (IHost host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(cfg =>
{
cfg.AddJsonFile("appsettings.json");
})
.ConfigureServices((context, services) =>
{
services.AddDbContext<EquitiesDbContext>(options => { options.UseSqlServer(context.Configuration.GetConnectionString("Equities")); });
services.AddScoped<ProgramAsync>();
})
.ConfigureLogging((context, cfg) =>
{
cfg.ClearProviders();
cfg.AddConfiguration(context.Configuration.GetSection("Logging"));
cfg.AddConsole();
})
.Build()
)
{
using( IServiceScope scope = host.Services.CreateScope() )
{
ProgramAsync p = scope.ServiceProvider.GetRequiredService<ProgramAsync>();
p.MainAsync().Wait();
}
}
Console.WriteLine("Done.");
}
}