如何使用通用主机生成器运行 .NET Core 控制台应用程序

ask*_*ids 62 c# console-application .net-core asp.net-core

我试图弄清楚如何使用主机构建器模式来运行控制台应用程序(而不是 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()
        ; 

}
Run Code Online (Sandbox Code Playgroud)

abd*_*sco 96

编辑: .NET 6 的更新位于 \xe2\x86\x93
\n.NET 7 或 .NET 8 没有太多变化。

\n
\n

我将从默认worker模板开始。它预装了必要的软件包。如果您已有项目,请安装Microsoft.Extensions.Hosting包。

\n
dotnet new worker -n MyCli\n
Run Code Online (Sandbox Code Playgroud)\n

然后打开Program.cs并构建主机。Worker如果您不想采用托管服务路线,请删除托管服务。

\n
dotnet new worker -n MyCli\n
Run Code Online (Sandbox Code Playgroud)\n

建立你的逻辑:

\n
internal class MyService\n{\n    // you can also inject other services\n    private ILogger<MyService> _logger;\n\n    public MyService(ILogger<MyService> logger)\n    {\n        _logger = logger;\n    }\n\n    public void DoSomething()\n    {\n        _logger.LogInformation("Doing something");\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后在 .ConfigureServices 方法中注册该类

\n
public class Program\n{\n    public static void Main(string[] args)\n    {\n        var host = CreateHostBuilder(args).Build();\n    }\n\n    public static IHostBuilder CreateHostBuilder(string[] args) =>\n        Host.CreateDefaultBuilder(args)\n            .ConfigureServices((hostContext, services) =>\n            {\n                // remove the hosted service\n                // services.AddHostedService<Worker>();\n\n                // register your services here.\n            });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在您可以在方法内解析并调用它Main

\n
internal class MyService\n{\n    // you can also inject other services\n    private ILogger<MyService> _logger;\n\n    public MyService(ILogger<MyService> logger)\n    {\n        _logger = logger;\n    }\n\n    public void DoSomething()\n    {\n        _logger.LogInformation("Doing something");\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

.NET 6+ 更新

\n

使用 .NET 6,样板代码显着减少。我们可以将我们的重写Program.cs为:

\n
Host.CreateDefaultBuilder(args)\n    .ConfigureServices((hostContext, services) =>\n    {\n        services.AddTransient<MyService>();\n    });\n
Run Code Online (Sandbox Code Playgroud)\n

  • 注意:使用“Microsoft.Extensions.Hosting”。可能需要一个 NuGet 包。 (3认同)
  • 有人可能还需要添加配置 - 请参阅[如何在 ASP .NET Core 中初始化主机之前读取配置设置?](//stackoverflow.com/a/58594026) (2认同)

Ric*_*ugh 9

基本上:

  • 实例化您的主机构建器并配置您的服务等等。

  • 为您的程序创建一个带有方法的类,并将该类注册为服务。

  • 构建主机,创建范围,获取类的实例,调用您的方法。

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.");
        }
    }

Run Code Online (Sandbox Code Playgroud)

  • 将 `Program.Main(..)` 声明为 `async Task Main(..)` 是合法的,并且允许您 `await p.MainAsync();` (4认同)