Skip to content

Commit d77d299

Browse files
committed
Rename HostingAction to HostingWrappingAction and remove BindingHandler dependency and extension methods
1 parent 38a4d69 commit d77d299

File tree

3 files changed

+8
-90
lines changed

3 files changed

+8
-90
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,11 @@
1-
using System.CommandLine.Binding;
2-
using System.CommandLine.Invocation;
3-
using System.CommandLine.NamingConventionBinder;
4-
using CommandHandler = System.CommandLine.NamingConventionBinder.CommandHandler;
1+
#nullable enable
52

6-
using Microsoft.Extensions.DependencyInjection;
73
using Microsoft.Extensions.Hosting;
8-
using Microsoft.Extensions.Options;
94

105
namespace System.CommandLine.Hosting
116
{
127
public static class HostingExtensions
138
{
14-
public static CommandLineConfiguration UseHost(
15-
this CommandLineConfiguration config,
16-
Func<string[], IHostBuilder> hostBuilderFactory,
17-
Action<IHostBuilder> configureHost = null)
18-
{
19-
if (config.RootCommand is RootCommand root)
20-
{
21-
root.Add(new Directive(HostingAction.HostingDirectiveName));
22-
}
23-
24-
HostingAction.SetHandlers(config.RootCommand, hostBuilderFactory, configureHost);
25-
26-
return config;
27-
}
28-
29-
public static CommandLineConfiguration UseHost(
30-
this CommandLineConfiguration config,
31-
Action<IHostBuilder> configureHost = null
32-
) => UseHost(config, null, configureHost);
33-
34-
public static OptionsBuilder<TOptions> BindCommandLine<TOptions>(
35-
this OptionsBuilder<TOptions> optionsBuilder)
36-
where TOptions : class
37-
{
38-
if (optionsBuilder is null)
39-
throw new ArgumentNullException(nameof(optionsBuilder));
40-
return optionsBuilder.Configure<IServiceProvider>((opts, serviceProvider) =>
41-
{
42-
var modelBinder = serviceProvider
43-
.GetService<ModelBinder<TOptions>>()
44-
?? new ModelBinder<TOptions>();
45-
var bindingContext = serviceProvider.GetRequiredService<BindingContext>();
46-
modelBinder.UpdateInstance(opts, bindingContext);
47-
});
48-
}
49-
50-
public static Command UseCommandHandler<THandler>(this Command command)
51-
where THandler : CommandLineAction
52-
{
53-
command.Action = CommandHandler.Create(typeof(THandler).GetMethod(nameof(AsynchronousCommandLineAction.InvokeAsync)));
54-
55-
return command;
56-
}
57-
589
public static ParseResult GetParseResult(this IHostBuilder hostBuilder)
5910
{
6011
_ = hostBuilder ?? throw new ArgumentNullException(nameof(hostBuilder));
@@ -76,12 +27,5 @@ public static ParseResult GetParseResult(this HostBuilderContext context)
7627

7728
throw new InvalidOperationException("Host builder context has no command-line parse result registered to it.");
7829
}
79-
80-
public static IHost GetHost(this ParseResult parseResult)
81-
{
82-
_ = parseResult ?? throw new ArgumentNullException(paramName: nameof(parseResult));
83-
var hostModelBinder = new ModelBinder<IHost>();
84-
return (IHost)hostModelBinder.CreateInstance(parseResult.GetBindingContext());
85-
}
8630
}
8731
}

src/System.CommandLine.Hosting/HostingAction.cs src/System.CommandLine.Hosting/HostingWrappingAction.cs

+6-32
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System.Collections.Generic;
2-
using System.CommandLine.Binding;
32
using System.CommandLine.Invocation;
4-
using System.CommandLine.NamingConventionBinder;
53
using System.Linq;
64
using System.Threading;
75
using System.Threading.Tasks;
@@ -12,7 +10,7 @@
1210
namespace System.CommandLine.Hosting
1311
{
1412
// It's a wrapper, that configures the host, starts it and then runs the actual action.
15-
internal sealed class HostingAction : BindingHandler
13+
internal sealed class HostingWrappingAction : AsynchronousCommandLineAction
1614
{
1715
internal const string HostingDirectiveName = "config";
1816

@@ -22,7 +20,7 @@ internal sealed class HostingAction : BindingHandler
2220

2321
internal static void SetHandlers(Command command, Func<string[], IHostBuilder> hostBuilderFactory, Action<IHostBuilder> configureHost)
2422
{
25-
command.Action = new HostingAction(hostBuilderFactory, configureHost, (AsynchronousCommandLineAction)command.Action);
23+
command.Action = new HostingWrappingAction(hostBuilderFactory, configureHost, (AsynchronousCommandLineAction)command.Action);
2624
command.TreatUnmatchedTokensAsErrors = false; // to pass unmatched Tokens to host builder factory
2725

2826
foreach (Command subCommand in command.Subcommands)
@@ -31,18 +29,13 @@ internal static void SetHandlers(Command command, Func<string[], IHostBuilder> h
3129
}
3230
}
3331

34-
private HostingAction(Func<string[], IHostBuilder> hostBuilderFactory, Action<IHostBuilder> configureHost, AsynchronousCommandLineAction actualAction)
32+
private HostingWrappingAction(Func<string[], IHostBuilder> hostBuilderFactory, Action<IHostBuilder> configureHost, AsynchronousCommandLineAction actualAction)
3533
{
3634
_hostBuilderFactory = hostBuilderFactory;
3735
_configureHost = configureHost;
3836
_actualAction = actualAction;
3937
}
4038

41-
public override BindingContext GetBindingContext(ParseResult parseResult)
42-
=> _actualAction is BindingHandler bindingHandler
43-
? bindingHandler.GetBindingContext(parseResult)
44-
: base.GetBindingContext(parseResult);
45-
4639
public override async Task<int> InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken = default)
4740
{
4841
var argsRemaining = parseResult.UnmatchedTokens;
@@ -76,35 +69,16 @@ public override async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
7669
}
7770
}
7871

79-
var bindingContext = GetBindingContext(parseResult);
80-
int registeredBefore = 0;
81-
hostBuilder.ConfigureServices(services =>
72+
hostBuilder.ConfigureServices(static (context, services) =>
8273
{
74+
var parseResult = context.GetParseResult();
8375
services.AddSingleton(parseResult);
84-
services.AddSingleton(bindingContext);
85-
86-
registeredBefore = services.Count;
8776
});
8877

89-
if (_configureHost is not null)
90-
{
91-
_configureHost.Invoke(hostBuilder);
92-
93-
hostBuilder.ConfigureServices(services =>
94-
{
95-
// "_configureHost" just registered types that might be needed in BindingContext
96-
for (int i = registeredBefore; i < services.Count; i++)
97-
{
98-
Type captured = services[i].ServiceType;
99-
bindingContext.AddService(captured, c => c.GetService<IHost>().Services.GetService(captured));
100-
}
101-
});
102-
}
78+
_configureHost?.Invoke(hostBuilder);
10379

10480
using var host = hostBuilder.Build();
10581

106-
bindingContext.AddService(typeof(IHost), _ => host);
107-
10882
await host.StartAsync(cancellationToken);
10983

11084
try

src/System.CommandLine.Hosting/System.CommandLine.Hosting.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4+
<LangVersion>12</LangVersion>
45
<IsPackable>true</IsPackable>
56
<TargetFrameworks>netstandard2.0;netstandard2.1;$(TargetFrameworkForNETSDK)</TargetFrameworks>
67
<Description>This package provides support for using System.CommandLine with Microsoft.Extensions.Hosting.</Description>
@@ -20,7 +21,6 @@
2021
</ItemGroup>
2122

2223
<ItemGroup>
23-
<ProjectReference Include="..\System.CommandLine.NamingConventionBinder\System.CommandLine.NamingConventionBinder.csproj" />
2424
<ProjectReference Include="..\System.CommandLine\System.CommandLine.csproj" />
2525
</ItemGroup>
2626

0 commit comments

Comments
 (0)