Closed JKamsker closed 7 months ago
Hi @JKamsker, I'm triaging the CLI issues and wanted to understand this one a bit better. My feeling is perhaps what you are asking for doesn't fit into the current spectre.console DI implementation pattern, but equally the existing functionality is sufficient.
I've knocked up the following example, as a test bed. Basically we have a service, service config, command, and command settings:
using Spectre.Console;
using Spectre.Console.Cli;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp1;
public interface IConnectionSettings
{
string ConnectionString { get; set; }
}
public interface IConnectionService
{
void ConnectToDatabase();
}
/// <summary>
/// Settings provider for the ConnectionService
/// </summary>
public sealed class ConnectionSettings : IConnectionSettings
{
public string ConnectionString { get; set; }
}
/// <summary>
/// Example database connection service
/// </summary>
public class ConnectionService : IConnectionService
{
private readonly IConnectionSettings settings;
public ConnectionService(IConnectionSettings settings)
{
this.settings = settings;
}
public void ConnectToDatabase()
{
// Establish a connection to the database
AnsiConsole.WriteLine($"Connecting to database, connection string: {settings.ConnectionString}");
}
}
public sealed class DatabaseCommandSettings : CommandSettings
{
[CommandOption("--DryRun <THE_VALUE>")]
public bool DryRun { get; set; }
}
public sealed class DatabaseCommand : Command<DatabaseCommandSettings>
{
public override int Execute(CommandContext context, DatabaseCommandSettings settings)
{
AnsiConsole.WriteLine($"DryRun: {settings.DryRun}");
return 0;
}
}
public class Program
{
static void Main(string[] args)
{
var connectionSettings = new ConnectionSettings() { ConnectionString = "server=127.0.0.1;user=bob;password=squarepants;" };
var registrations = new ServiceCollection();
registrations.AddSingleton<IConnectionSettings>(connectionSettings);
registrations.AddSingleton<IConnectionService, ConnectionService>();
var registrar = new TypeRegistrar(registrations);
var app = new CommandApp<DatabaseCommand>(registrar);
app.Run(args);
}
}
(nb, the above uses the following implementations: TypeRegistrar, TypeResolver)
In the above example, the command and service are unrelated, and executing the application with ConsoleApp1.exe --DryRun
just runs the command, ie:
I suspect this issue is asking for DatabaseCommandSettings
to somehow be injected into ConnectionService
- is that correct @JKamsker?
I cannot think of an easy way to do that, given the TypeResolver
is populated prior to the CommandSettings
being created off the args, and then provided to the command when the Execute
method is called.
Equally, the following modification to the DatabaseCommand will inject the ConnectionService
into the DatabaseCommand
:
public sealed class DatabaseCommand : Command<DatabaseCommandSettings>
{
IConnectionService connectionService;
public DatabaseCommand(IConnectionService connectionService)
{
this.connectionService = connectionService;
}
public override int Execute(CommandContext context, DatabaseCommandSettings settings)
{
AnsiConsole.WriteLine($"DryRun: {settings.DryRun}");
connectionService.ConnectToDatabase();
return 0;
}
}
This allows the command to propagate whatever command settings it wishes when making calls on the service.
Does this fully satisfy the issue, or have I misunderstood the ask?
If so, can you please annotate my code example above, with the specific usage pattern being requested?
The problem was that i wanted to get the connectionstring from the settings. Ig that issue can be resolved now, because interceptors got enhanced.
My solution:
IHasConnectionString
Is your feature request related to a problem? Please describe. I have a service that is registered with di in IServiceCollection. It would be nice if that service could access the settings, so that it doesnt have to be initialized by the command itself. The settings implement a specific baseclass or interface.
Describe the solution you'd like
or
or through DI:
With this approach, ConnectionService cannot be instantiated without Settings implementing IHasConnectionString.
Describe alternatives you've considered I've looked into the source of SpectreConsole and did not find any alternative way. Only other option would be to parse the settings myself.