-
Notifications
You must be signed in to change notification settings - Fork 395
/
Copy pathHostingExtensions.cs
114 lines (95 loc) · 4.8 KB
/
HostingExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System.CommandLine.Binding;
using System.CommandLine.Builder;
using System.CommandLine.Invocation;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace System.CommandLine.Hosting
{
public static class HostingExtensions
{
private const string ConfigurationDirectiveName = "config";
public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Func<string[], IHostBuilder> hostBuilderFactory,
Action<IHostBuilder> configureHost = null) =>
builder.UseMiddleware(async (invocation, next) =>
{
var argsRemaining = invocation.ParseResult.UnparsedTokens.ToArray();
var hostBuilder = hostBuilderFactory?.Invoke(argsRemaining)
?? new HostBuilder();
hostBuilder.Properties[typeof(InvocationContext)] = invocation;
hostBuilder.ConfigureHostConfiguration(config =>
{
config.AddCommandLineDirectives(invocation.ParseResult, ConfigurationDirectiveName);
});
hostBuilder.ConfigureServices(services =>
{
services.AddSingleton(invocation);
services.AddSingleton(invocation.BindingContext);
services.AddSingleton(invocation.Console);
services.AddTransient(_ => invocation.InvocationResult);
services.AddTransient(_ => invocation.ParseResult);
});
hostBuilder.UseInvocationLifetime(invocation);
configureHost?.Invoke(hostBuilder);
using var host = hostBuilder.Build();
invocation.BindingContext.AddService(typeof(IHost), _ => host);
await host.StartAsync();
await next(invocation);
await host.StopAsync();
});
public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Action<IHostBuilder> configureHost = null
) => UseHost(builder, null, configureHost);
public static IHostBuilder UseInvocationLifetime(this IHostBuilder host,
InvocationContext invocation, Action<InvocationLifetimeOptions> configureOptions = null)
{
return host.ConfigureServices(services =>
{
services.TryAddSingleton(invocation);
services.AddSingleton<IHostLifetime, InvocationLifetime>();
if (configureOptions is Action<InvocationLifetimeOptions>)
services.Configure(configureOptions);
});
}
public static OptionsBuilder<TOptions> BindCommandLine<TOptions>(
this OptionsBuilder<TOptions> optionsBuilder)
where TOptions : class
{
if (optionsBuilder is null)
throw new ArgumentNullException(nameof(optionsBuilder));
return optionsBuilder.Configure<IServiceProvider>((opts, serviceProvider) =>
{
var modelBinder = serviceProvider
.GetService<ModelBinder<TOptions>>()
?? new ModelBinder<TOptions>();
var bindingContext = serviceProvider.GetRequiredService<BindingContext>();
modelBinder.UpdateInstance(opts, bindingContext);
});
}
public static InvocationContext GetInvocationContext(this IHostBuilder hostBuilder)
{
_ = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder));
if (hostBuilder.Properties.TryGetValue(typeof(InvocationContext), out var ctxObj) &&
ctxObj is InvocationContext invocationContext)
return invocationContext;
throw new InvalidOperationException("Host builder has no Invocation Context registered to it.");
}
public static InvocationContext GetInvocationContext(this HostBuilderContext context)
{
_ = context ?? throw new ArgumentNullException(nameof(context));
if (context.Properties.TryGetValue(typeof(InvocationContext), out var ctxObj) &&
ctxObj is InvocationContext invocationContext)
return invocationContext;
throw new InvalidOperationException("Host builder has no Invocation Context registered to it.");
}
public static IHost GetHost(this InvocationContext invocationContext)
{
_ = invocationContext ?? throw new ArgumentNullException(paramName: nameof(invocationContext));
var hostModelBinder = new ModelBinder<IHost>();
return (IHost)hostModelBinder.CreateInstance(invocationContext.BindingContext);
}
}
}