dotnet / dotnet/command-line-api
.NET Generic Host and Dependency Injection
- Dominant language
- C#
- Stars
- 3.7k
- Forks
- 428
- PR merge metrics
- No merged PRs in 30d
Description
As best as I can tell, there doesn't seem to be a good way to automatically inject host services into SetHandler Func and Action; the only services injectable are those registered on the binding context.
```c#
public interface IFoo { }
public class Foo : IFoo { }
public class Program
{
public static async Task Main(string[] args)
{
var command = new RootCommand();
command.SetHandler((foo) =>
{
Console.WriteLine($"We have received an IFoo of type {foo.GetType()}");
});
var builder = new CommandLineBuilder(command);
var runner = builder.UseHost(
_ => Host.CreateDefaultBuilder(args),
hostBuilder =>
{
hostBuilder.ConfigureServices(services =>
{
services.AddSingleton();
});
})
.Build();
await runner.InvokeAsync(args);
}
}
```
The above example will always result in an argument exception, complaining about not being able to find a service of type ```IFoo```. This is because ```BindingContext``` only consults its internal set of registered / parsed services.
I couldn't figure out a way to make this work without doing things like manually injecting services into the ```BindingContext``` as part of an invocation middleware, or fetching the ```InvocationContext```, using that to retrieve the IHost instance, and then using the retrieved IHost instance to resolve my services within my handler. This seems messy.
I hacked together a change with a few tests (more are needed) to improve this scenario; I added the ability to register additional ```IServiceProvider``` instances to the ```BindingContext```, modified ```BindingContext``` to consult these additional instances when handling calls to GetService, and then added an extension method in ```System.CommandLine.Hosting``` that wires up the host ```IServiceProvider``` instance to the binding context as part of middleware.
I thought this might be a useful addition, a draft PR is here. I also thought I might be completely off base here, and there is a better way of doing this. 😄 I am happy with either outcome.
Draft PR https://github.com/dotnet/command-line-api/pull/1568
Contributor guide
Assessment
This issue has not been assessed yet.