dotnet / dotnet/command-line-api

Add UseHost for WebApplicationBuilder (or maybe IHostApplicationBuilder)

Aperta
#2,268 4 commenti 3 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
C#
Stelle
3.7k
Fork
428
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

My team maintains a bunch of http apis using asp core. We've added a cli interface to each app because tho starting kestrel is the main case, there are several others, for example

- configure backing services (eg, an auth provider)
- run migrations
- self-check: is all necessary configuration available?

Some are only invoked when running on a local dev machine, others are used in deploy pipelines.

The included System.CommandLine.Hosting.HostingExtensions has a `UseHost` for an `IHostBuilder`, but the host build object I have is an `WebApplicationBuilder`. Building the entire host is somewhat expensive, to be sure. But it's useful enough to be worth it, and the things we're running need most of the app anyway.

So I copied the UseHost function and swapped in the WebApplicationBuilder type. Mostly it's the same, except that the host is neither stopped nor started. I want the command handlers to decide whether or not to start the host! My RunWebApi handler does start the host, but my SelfCheck handler only needs the built host's ServicesCollection.

Does it make sense to add this extension method to the library? As I wrote this out, I realized that maybe IHostApplicationBuilder is a better type than WebApplicationBuilder, but the idea stands.

```csharp
using System.CommandLine.Builder;
using System.CommandLine.Invocation;

namespace System.CommandLine.Hosting;

public static class HostingExtensions
{
private const string ConfigurationDirectiveName = "config";
public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Func hostBuilderFactory,
Action? configureHost = null) =>
builder.AddMiddleware(async (invocation, next) =>
{
var argsRemaining = invocation.ParseResult.UnparsedTokens.ToArray();
var hostBuilder = hostBuilderFactory.Invoke(argsRemaining);
hostBuilder.Host.Properties[typeof(InvocationContext)] = invocation;

hostBuilder.Host.ConfigureHostConfiguration(config =>
{
config.AddCommandLineDirectives(invocation.ParseResult, ConfigurationDirectiveName);
});
hostBuilder.Host.ConfigureServices(services =>
{
services.AddSingleton(invocation);
services.AddSingleton(invocation.BindingContext);
services.AddSingleton(invocation.Console);
services.AddTransient(_ => invocation.InvocationResult);
services.AddTransient(_ => invocation.ParseResult);
});
hostBuilder.Host.UseInvocationLifetime(invocation);
configureHost?.Invoke(hostBuilder);

using var host = hostBuilder.Build();

invocation.BindingContext.AddService(typeof(WebApplication), _ => host);

// await host.StartAsync(); // no: let cli handlers decide if they want to start the host

await next(invocation);

// await host.StopAsync(); // don't stop what wasn't started
});
```

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Leggere l’overload esistente di System.CommandLine.Hosting.HostingExtensions.UseHost per IHostBuilder e confrontarlo con la versione proposta per WebApplicationBuilder o IHostApplicationBuilder. Stabilire quale tipo di builder e quali semantiche del ciclo di vita debbano essere supportati, quindi validare l’estensione rispetto agli scenari CLI mostrati, inclusi gli handler che avviano l’host e quelli che usano solo i suoi servizi.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
csharp
Ambito
backend-api-design, cli
Tipo di issue
Funzionalità
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.