question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support ASP.NET Core Generic Hosts

See original GitHub issue

ASP.NET Core Generic Hosts are a great way to handle background tasks. Unfortunately, Generic Hosts don’t do anything fancy for command line parsing. That’s where CommandLineUtils comes in!

The basic idea is that CommandLineUtils should parse the command line arguments to figure out which IHostedService to register.

Attribute Pattern

In the attribute pattern, I suggest that CommandLineUtils registers the matched type using the host’s AddHostedService if the matched type is an IHostedService. For example:

public class Program : IHostedService
{
    public static int Main(string[] args)
        => await new HostBuilder()
            .UseCommandLineApplication<Program>(args) // CommandLineUtils extension!
            .RunConsoleAsync();

    [Option(Description = "The subject")]
    public string Subject { get; }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        var subject = Subject ?? "world";
        Console.WriteLine($"Hello {subject}!");
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

Fluent apps

For fluent apps, I suggest we add some extensions on IHostBuilder:

public class Program
{
    public static Task Main(string[] args)
    {
        await new HostBuilder()
            .UseCommandLineApplication(args, (hostContext, services, app) =>
            {
                app.HelpOption();
                var optionSubject = app.Option("-s|--subject <SUBJECT>", "The subject", CommandOptionType.SingleValue);

                // (1/3) "Traditional" approach:
                app.OnExecute(services =>
                {
                    var subject = optionSubject.HasValue()
                        ? optionSubject.Value()
                        : "world";

                    // This is a little icky. We pass the subject option through the service's constructor:
                    services.AddHostedService<HelloService>(provider => new HelloService(subject));
                });

                // (2/3) Alternate approach:
                // This creates a delegate-based `BackgroundService` that captures local options
                app.RunBackgroundService(CancellationToken token =>
                {
                    var subject = optionSubject.HasValue()
                        ? optionSubject.Value()
                        : "world";

                    Console.WriteLine($"Hello {subject}!");
                });

                // (3/3) Stretch goal:
                // Something else I'd like are short-lived commands that do a task
                // and then automatically shut down the .NET Generic Host after completion
                app.RunCommand(CancellationToken token =>
                {
                    var subject = optionSubject.HasValue()
                        ? optionSubject.Value()
                        : "world";

                    // After this returns, the host is shutdown gracefully.
                    Console.WriteLine($"Hello {subject}!");
                });
            })
            .RunConsoleAsync();
    }
}

public class HelloService : BackgroundService
{
    private readonly string _subject;

    public HelloService(string subject)
    {
        _subject = subject;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        Console.WriteLine($"Hello {_subject}!");
    }
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
lucastheisencommented, Oct 19, 2018

@natemcmaster , i submitted the pull req. I created it as a separate package using the namespace you suggested (i think it is the correct namespace as it is basically an extension of Hosting that adds the CLI stuff, though the inverse is also true). I updated the dependency injection documentation to include a section for using generic host, and added a sample. However, I did not have any unit tests, so if that is necessary, i will have to figure out how to make that happen. Anyway, let me know what you think.

2reactions
natemcmastercommented, Aug 10, 2018

I really like this idea. I don’t have time to work on it right now, so I’ll mark it as up for grabs. If you want to get started on an implementation, let me know.

Read more comments on GitHub >

github_iconTop Results From Across the Web

NET Generic Host in ASP.NET Core
Use .NET Core Generic Host in ASP.NET Core apps. Generic Host is responsible for app startup and lifetime management.
Read more >
Understanding .NET Generic Host Model
ASP.NET Core apps configure and launch a host. The host is responsible for app startup and lifetime management. At a minimum, the host...
Read more >
NET Core Startup class & Generic Host
NET Generic Host, which is a non-web version of the WebHost that runs ASP.NET Core. In ASP.NET Core 3.0 and 3.1, they moved...
Read more >
Building a Console App with .NET Generic Host | David's Blog
The .NET Generic Host is a feature which sets up some convenient patterns for an application including those for dependency injection (DI), ...
Read more >
Using HostBuilder and the Generic Host in .NET Core ...
NET Core 2.1 is the new “generic” Host which enables developers to easily set up cross-cutting concerns such as logging, configuration and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found