如何使用通用主机构建器运行.NET Core Console应用程序

发布于 2025-01-20 09:35:35 字数 832 浏览 4 评论 0原文

我正在尝试弄清楚如何使用主机构建器模式运行控制台应用程序(而不是Windows服务)。目的是使流量与WebAPI相似,以使开发实践相似。我已经看到了使用托管服务或背景服务的样本,他们想在其中运行它作为Windows服务。但是,如果我想运行一个简单的控制台应用程序,我在哪里指定入门点类和方法?从hostbuilder.build(),我可以看到run()和runAsync()方法。但是我无法弄清楚它会执行什么?

我已经看到了您可以在哪里创建serviceCollection,然后使用serviceProvider.getService()。somemethod()开始过程的其他示例。但是这种偏离我们想做的事情。因此,请建议如何指定启动过程。我们使用的是3.1 .NET核心。

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()
        ; 

}

I am trying to figure out how to use hostbuilder pattern to run a console app (not a windows service). Intent is to keep the flow as similar to a WebApi to keep development practices similar. I have seen samples for using HostedService or BackGroundService, where they want to run it as a windows service. But If I am looking to run a simple console app, where do I specify my entrypoint class and method? From hostbuilder.Build(), I can see Run() and RunAsync() methods. But I am unable to figure out what will it execute?

I have seen other examples of where you can create servicecollection and then use serviceprovider.GetService().SomeMethod() to start the process. But that kind of deviates from what we want to do. So please suggest how to specify startup process. We are using 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()
        ; 

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜访吸血鬼 2025-01-27 09:35:35

编辑: .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+ 更新

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

EDIT: An update for .NET 6 is below ↓
Not much has changed with .NET 7 or .NET 8.


I'd start off with the default worker template. It comes with necessary packages pre-installed. If you already have a project, install Microsoft.Extensions.Hosting package.

dotnet new worker -n MyCli

Then open up the Program.cs and build the host. Remove the Worker hosted service if you don't want to go with the hosted service route.

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

Build your logic:

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

Then register the class inside .ConfigureServices method

Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddTransient<MyService>();
    });

Now you can resolve and call it inside the Main method:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    var myService = host.Services.GetRequiredService<MyService>();
    myService.DoSomething();
}

.NET 6+ update

With .NET 6, boilerplate is reduced significantly. We can rewrite our Program.cs as:

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");
    }
}
鹿! 2025-01-27 09:35:35

基本上:

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

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

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

我的程序是我的类 ProgramAsync 中的方法 MainAsync

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

Basically:

  • Instantiate your host builder and configure your services and whatnot.

  • Make a class with a method for your programme and register that class as a service.

  • Build the host, create a scope, get an instance of your class, call your method.

My programme is the mehod MainAsync in my class 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.");
        }
    }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文