DI: How to register Service, that needs parsed argument as parameter
Hi, i want to build a cli wrapper around an existing API. The API is instantiated with a static factory method which has a parameter called environment (PROD or TEST). This environment should be an option for the cli. How do i register the service properly to use it in Commands with DI?
Hi @SvenBM
I think I didn't understand the question correctly. Do you mean to register a service depending on the result of the CLI Option i.e. the PROD/TEST?
Maybe something like this is a solution?
Run
> wrapper.exe -e prod run
> Running API from PROD
Code
using MatthiWare.CommandLine;
using MatthiWare.CommandLine.Abstractions;
using MatthiWare.CommandLine.Abstractions.Command;
using MatthiWare.CommandLine.Core.Attributes;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Reflection;
namespace Question
{
public enum ApiEnvironment
{
PROD,
TEST
}
public class Options
{
[Name("e", "environment")]
[Required]
public ApiEnvironment Environment { get; set; }
}
public class Api
{
private readonly ApiEnvironment environment;
private Api(ApiEnvironment environment)
{
this.environment = environment;
}
public static Api CreateApiFactory(ApiEnvironment environment)
=> new(environment);
public void Run()
{
Console.WriteLine($"Running API from {environment}");
}
}
public class RunCommand : Command<Options>
{
public override void OnConfigure(ICommandConfigurationBuilder builder)
{
builder.Name("run").Description("Runs the API");
}
public override void OnExecute(Options options)
{
var api = Api.CreateApiFactory(options.Environment);
api.Run();
}
public class Program
{
static void Main(string[] args)
{
var services = ConfigureServices();
var parser = services.BuildServiceProvider().GetRequiredService<ICommandLineParser<Options>>();
parser.DiscoverCommands(Assembly.GetExecutingAssembly());
parser.Parse(args);
}
static IServiceCollection ConfigureServices()
{
var services = new ServiceCollection();
services.AddCommandLineParser<Options>();
return services;
}
}
}
}
Hey, thx for your fast reply. Yes, you got it right, despite that my API has an interface. But when i code it like this, i have to instantiate the API in every command (there are more than 1). It would by nicer if i could register the API's interface to the services and then inject it into the command - the DI-container should be responsible for creating instances. Do you see some way? Or is it prohibited by the parse-executeCommand-chain?
At the moment it is not possible to do this because the result of which API environment to use is only known after the service provider has already been built.