-
Notifications
You must be signed in to change notification settings - Fork 386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dependency injection confusion - How to use CommandLineBuilder, UseHost, CommandHandlers etc #1858
Comments
Whoops! This works a lot better when I pass
Will keep this open and see if I can get a complete example working. |
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Hosting;
using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
namespace Test2
{
internal class Program
{
static void Main(string[] args)
{
var parser = new CommandLineBuilder(new MyCommand())
.UseHost(host =>
{
host.ConfigureServices(services =>
{
services.AddSingleton<IGreetingService, HelloService>();
services.AddSingleton<IFarewellService, FarewellService>();
services.Configure<FarewellOptions>(f => f.CustomFarewell = "Until we meet again");
})
.UseCommandHandler<MyCommand, MyCommandHandler>();
})
.Build();
var parseResult = parser.Parse(args);
var invokeResult = parser.Invoke(args);
}
}
public class MyCommandHandler : ICommandHandler
{
private readonly IGreetingService _greetingService;
private readonly IFarewellService _farewellService;
private readonly IOptions<FarewellOptions> _options;
public MyCommandHandler(IGreetingService greetingService, IFarewellService farewellService, IOptions<FarewellOptions>? farewellOptions)
{
_greetingService = greetingService;
_farewellService = farewellService;
_options = farewellOptions;
}
public int Invoke(InvocationContext context)
{
throw new NotImplementedException();
}
public Task<int> InvokeAsync(InvocationContext context)
{
Console.WriteLine(_greetingService.Greet());
Console.WriteLine(_farewellService.Farewell());
return Task.FromResult(0);
}
}
internal class MyCommand : RootCommand
{
public MyCommand() : base("")
{
var farewellOption = new Option<string>("--farewell");
this.AddOption(farewellOption);
}
}
public class FarewellOptions
{
public string CustomFarewell { get; set; }
}
public interface IGreetingService
{
string Greet();
}
public interface IFarewellService
{
string Farewell();
}
public class HelloService : IGreetingService
{
public HelloService()
{
}
public string Greet()
{
return "Hello!";
}
}
public class FarewellService : IFarewellService
{
private IOptions<FarewellOptions> _options;
public FarewellService(IOptions<FarewellOptions> options)
{
_options = options;
}
public string Farewell()
{
if (!string.IsNullOrEmpty(_options.Value.CustomFarewell))
{
return _options.Value.CustomFarewell;
}
return "Farewell!";
}
}
} Gets me much closer - from my initial list I can do everything except configure services from the command line. For my contrived example,
|
Do you know if there is a working example where multiple commands/handlers are wired with |
Does this test case help illustrate the usage? command-line-api/src/System.CommandLine.Hosting.Tests/HostingHandlerTest.cs Lines 57 to 86 in 5618b2d
|
Sort of, I don't think it shows how to get access to multiple services though. |
One scenario I wasn't quite able to figure out myself was if my root command wanted to leverage constructor DI, I wasn't seeing how to implement that when you need to create an instance of the root to pass into the CommandLineBuilder constructor. Or is it simply root commands have to be constrained to something very simplistic and they should be thought of as more of an 'anchor point' for your set of top-level sub-commands than providing functionality in the root itself. |
I have started work on PR #2450 where I will add new examples to |
I'm lost in the weeds with dependency injection here.
Before I even get to using the Hosting stuff, why is RootCommand set to Test2 when that's not in
args[]
and why aren'tMyCommand
andMyCommandHandler
not called at all - shouldn't I be getting aNotImplementedException
?I've looked at https://github.com/dotnet/command-line-api/blob/5618b2d243ccdeb5c7e50a298b33b13036b4351b/src/System.CommandLine.Hosting.Tests/HostingHandlerTest.cs and #1025 (comment) but have not been able to make much progress.
https://learn.microsoft.com/en-us/dotnet/standard/commandline/dependency-injection isn't entirely suitable because I need multiple services after my command line is parsed.
Further away from my simplified example, I'd like something like the following to work:
So I am stuck on:
Thanks in advance - sorry if I've completely missed the mark here.
The text was updated successfully, but these errors were encountered: