Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions samples/CommandLineSample.Standalone/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,14 @@
Option<string> limitOption = new("--limit", "-l")
{
Description = "Max amount of products to display.",

};

Option<string> headerOption = new("--header", "-h")
{
Description = "Header to display above product results."
};

AutomationCommand rootCommand =
AutomationRootCommand rootCommand =
AutomationConsole.CreateRootCommand(
commandAutomationContext,
"Sample CommandLine Example (with standalone commands)");
Expand All @@ -75,16 +74,23 @@
// Manual Command Building Example
AutomationCommand subCommand = rootCommand.AddCommand("report", "Generate various reports");

subCommand.Options.Add(reportTypeOption);
subCommand.Options.Add(limitOption);
subCommand.Options.Add(headerOption);
subCommand.Add(reportTypeOption);
subCommand.Add(limitOption);
subCommand.Add(headerOption);

subCommand.SetAction((result, automationContext) =>
{
// Report Type and Limit are mapped to configuration via
// the AutomationContext ConfigurationMapping set in SetConfigurationMapping (above)
string reportType = result.GetValue<string>(reportTypeOption);
string limit = result.GetValue<string>(limitOption);
string headerText = result.GetValue<string>(headerOption);

Console.WriteLine($"Report Type (Override): {reportType}");
Console.WriteLine($"Limit (Override): {limit}");
Console.WriteLine("Generating report...");

string headerText = result.GetValue<string>(headerOption);

UpdateGreeting(headerText, automationContext.ServiceProvider.GetService<IReportService>());
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"CommandLineSample (Standalone) - Automation": {
"commandName": "Project",
"commandLineArgs": "report-automated --header test --limit 5 -t Company"
},
"CommandLineSample (Standalone) - Help": {
"commandName": "Project",
"commandLineArgs": "report --help"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace CommandLineSample.Standalone;

internal class ReportCommandInitializer : IAutomationCommandInitializer
{
public void Initialize(AutomationCommand command)
public void Initialize(IAutomationCommand command)
{
Option<string> reportTypeOption = new("--optionOne", "-t")
{
Expand All @@ -30,14 +30,21 @@ public void Initialize(AutomationCommand command)
Description = "Header to display above product results."
};

command.Options.Add(reportTypeOption);
command.Options.Add(limitOption);
command.Options.Add(headerOption);
command.Add(reportTypeOption);
command.Add(limitOption);
command.Add(headerOption);

command.SetAction((result, automationContext) =>
{
// Report Type and Limit are mapped to configuration via
// the AutomationContext ConfigurationMapping set up in Program.cs
string reportType = result.GetValue<string>(reportTypeOption);
string limit = result.GetValue<string>(limitOption);

Console.WriteLine($"Report Type (Override): {reportType}");
Console.WriteLine($"Limit (Override): {limit}");
Console.WriteLine("Generating report...");

string headerText = result.GetValue<string>(headerOption);

UpdateGreeting(headerText, automationContext.ServiceProvider.GetService<IReportService>());
Expand Down
17 changes: 12 additions & 5 deletions samples/CommandLineSample/ReportCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace CommandLineSample;

internal class ReportCommand : IAutomationCommandInitializer
{
public void Initialize(AutomationCommand command)
public void Initialize(IAutomationCommand command)
{
Option<string> reportTypeOption = new("--optionOne", "-t")
{
Expand All @@ -30,16 +30,23 @@ public void Initialize(AutomationCommand command)
Description = "Header to display above product results."
};

command.Options.Add(reportTypeOption);
command.Options.Add(limitOption);
command.Options.Add(headerOption);
command.Add(reportTypeOption);
command.Add(limitOption);
command.Add(headerOption);

command.SetAction((result, automationContext) =>
{
// Report Type and Limit are mapped to configuration via
// the AutomationContext ConfigurationMapping set up in Program.cs
string reportType = result.GetValue<string>(reportTypeOption);
string limit = result.GetValue<string>(limitOption);
string headerText = result.GetValue<string>(headerOption);

Console.WriteLine($"Report Type (Override): {reportType}");
Console.WriteLine($"Limit (Override): {limit}");
Console.WriteLine("Generating report...");

string headerText = result.GetValue<string>(headerOption);

UpdateGreeting(headerText, automationContext.ServiceProvider.GetService<IReportService>());
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace AutomationIoC.CommandLine.Application;

internal class AutomationConsoleApplication(
AutomationCommand rootCommand,
AutomationRootCommand rootCommand,
string[]? arguments = null) : IAutomationConsole
{
private readonly string[] arguments = arguments ?? Environment.GetCommandLineArgs();
Expand Down
20 changes: 5 additions & 15 deletions src/CommandLine/src/AutomationCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,17 @@ namespace AutomationIoC.CommandLine;
/// <param name="automationContext">Automation Services and configurations</param>
public class AutomationCommand(
string name,
string? description,
IAutomationContext automationContext) : Command(name, description)
IAutomationContext automationContext,
string? description = null) : Command(name, description), IAutomationCommand
{
/// <summary>
/// Services and configurations for dependency injection.
/// </summary>
/// <inheritdoc />
public IAutomationContext Context => automationContext;

/// <summary>
/// Set the action to be executed when the command is invoked (synchronous).
/// The action receives the parsed result and the automation context, allowing for dependency injection.
/// </summary>
/// <param name="action">Dependency Injection Action for synchronous command invocation</param>
/// <inheritdoc />
public void SetAction(Action<ParseResult, IAutomationContext> action) =>
SetAction(parsedResult => action(parsedResult, automationContext));

/// <summary>
/// Set the action to be executed when the command is invoked (asynchronous).
/// The action receives the parsed result and the automation context, allowing for dependency injection.
/// </summary>
/// <param name="action">Dependency Injection Action for asynchronous command invocation</param>
/// <inheritdoc />
public void SetAction(Func<ParseResult, IAutomationContext, CancellationToken, Task> action) =>
SetAction(async (parsedResult, cancellationToken) =>
{
Expand Down
34 changes: 27 additions & 7 deletions src/CommandLine/src/AutomationCommandExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// Licensed under the MIT License
// -------------------------------------------------------

using System.CommandLine;

namespace AutomationIoC.CommandLine;

/// <summary>
Expand All @@ -20,7 +22,7 @@ public static class AutomationCommandExtensions
/// <returns>New Child Command</returns>
/// <exception cref="InvalidOperationException">Thrown if parent does not have an established automation context</exception>
public static AutomationCommand AddCommand<T>(
this AutomationCommand parentCommand,
this IAutomationCommand parentCommand,
string name,
string description)
where T : IAutomationCommandInitializer, new()
Expand All @@ -30,10 +32,19 @@ public static AutomationCommand AddCommand<T>(
throw new InvalidOperationException("Parent Command is missing automation context.");
}

var childAutomationCommand = new AutomationCommand(name, description, parentCommand.Context);
var childAutomationCommand = new AutomationCommand(name, parentCommand.Context, description);
var commandInitializer = new T();
commandInitializer.Initialize(childAutomationCommand);
parentCommand.Subcommands.Add(childAutomationCommand);

if (parentCommand is Command parentAsCommand)
{
parentAsCommand.Add(childAutomationCommand);
}
else
{
throw new InvalidOperationException(
"Parent Command must inherit from System.CommandLine.Command to add subcommands.");
}

return childAutomationCommand;
}
Expand All @@ -47,17 +58,26 @@ public static AutomationCommand AddCommand<T>(
/// <returns>New Child Command</returns>
/// <exception cref="InvalidOperationException"></exception>
public static AutomationCommand AddCommand(
this AutomationCommand parentCommand,
this IAutomationCommand parentCommand,
string name,
string description)
{
if (parentCommand.Context is null)
if (parentCommand?.Context is null)
{
throw new InvalidOperationException("Parent Command is missing automation context.");
}

var childAutomationCommand = new AutomationCommand(name, description, parentCommand.Context);
parentCommand.Subcommands.Add(childAutomationCommand);
var childAutomationCommand = new AutomationCommand(name, parentCommand.Context, description);

if (parentCommand is Command parentAsCommand)
{
parentAsCommand.Add(childAutomationCommand);
}
else
{
throw new InvalidOperationException(
"Parent Command must inherit from System.CommandLine.Command to add subcommands.");
}

return childAutomationCommand;
}
Expand Down
13 changes: 6 additions & 7 deletions src/CommandLine/src/AutomationConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using AutomationIoC.CommandLine.Builder;
using AutomationIoC.Runtime;
using System.CommandLine;

namespace AutomationIoC.CommandLine;

Expand All @@ -26,7 +25,7 @@ public static IAutomationConsoleBuilder CreateDefaultBuilder(string? appDescript
var automationContext = new AutomationContext();

var newAutomationCommand =
new AutomationCommand(RootCommand.ExecutableName, appDescription ?? string.Empty, automationContext);
new AutomationRootCommand(automationContext, appDescription ?? string.Empty);

return new AutomationConsoleBuilder(newAutomationCommand, automationContext, args);
}
Expand All @@ -49,7 +48,7 @@ public static IAutomationConsoleBuilder CreateDefaultBuilder<T>(
var automationCommandInitializer = new T();

var newAutomationCommand =
new AutomationCommand(RootCommand.ExecutableName, appDescription ?? string.Empty, automationContext);
new AutomationRootCommand(automationContext, appDescription ?? string.Empty);

automationCommandInitializer.Initialize(newAutomationCommand);

Expand All @@ -63,12 +62,12 @@ public static IAutomationConsoleBuilder CreateDefaultBuilder<T>(
/// <param name="automationContext">Automation context responsible for services <see cref="AutomationContext" /></param>
/// <param name="appDescription">Description of application tooling</param>
/// <returns>Root Automation Command</returns>
public static AutomationCommand CreateRootCommand(
public static AutomationRootCommand CreateRootCommand(
IAutomationContext automationContext,
string? appDescription = null)
{
var rootCommand =
new AutomationCommand(RootCommand.ExecutableName, appDescription ?? string.Empty, automationContext);
new AutomationRootCommand(automationContext, appDescription ?? string.Empty);

return rootCommand;
}
Expand All @@ -81,15 +80,15 @@ public static AutomationCommand CreateRootCommand(
/// <param name="appDescription">Description of application tooling</param>
/// <typeparam name="T"></typeparam>
/// <returns>Root Automation Command</returns>
public static AutomationCommand CreateRootCommand<T>(
public static AutomationRootCommand CreateRootCommand<T>(
IAutomationContext automationContext,
string? appDescription = null)
where T : IAutomationCommandInitializer, new()
{
var automationCommandInitializer = new T();

var rootCommand =
new AutomationCommand(RootCommand.ExecutableName, appDescription ?? string.Empty, automationContext);
new AutomationRootCommand(automationContext, appDescription ?? string.Empty);

automationCommandInitializer.Initialize(rootCommand);

Expand Down
32 changes: 32 additions & 0 deletions src/CommandLine/src/AutomationRootCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// -------------------------------------------------------
// Copyright (c) Ken Swan. All rights reserved.
// Licensed under the MIT License
// -------------------------------------------------------

using AutomationIoC.Runtime;
using System.CommandLine;

namespace AutomationIoC.CommandLine;

/// <summary>
/// Extends root command class with built-in dependency injection support for actions.
/// All sub-commands should inherit from AutomationCommand to leverage dependency injection.
/// </summary>
public class AutomationRootCommand(
IAutomationContext automationContext,
string description = "") : RootCommand(description), IAutomationCommand
{
/// <inheritdoc />
public IAutomationContext Context => automationContext;

/// <inheritdoc />
public void SetAction(Action<ParseResult, IAutomationContext> action) =>
SetAction(parsedResult => action(parsedResult, automationContext));

/// <inheritdoc />
public void SetAction(Func<ParseResult, IAutomationContext, CancellationToken, Task> action) =>
SetAction(async (parsedResult, cancellationToken) =>
{
await action(parsedResult, automationContext, cancellationToken).ConfigureAwait(false);
});
}
6 changes: 3 additions & 3 deletions src/CommandLine/src/Builder/AutomationConsoleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace AutomationIoC.CommandLine.Builder;

internal class AutomationConsoleBuilder(
AutomationCommand rootCommand,
AutomationRootCommand rootCommand,
AutomationContext automationContext,
string[]? args = null) : IAutomationConsoleBuilder
{
Expand Down Expand Up @@ -50,7 +50,7 @@ public IAutomationConsoleBuilder AddCommand<T>(params string[] commandPath)
var automationCommandInitializer = new T();

var newAutomationCommand =
new AutomationCommand(addedCommandName, null, automationContext);
new AutomationCommand(addedCommandName, automationContext);

automationCommandInitializer.Initialize(newAutomationCommand);

Expand Down Expand Up @@ -88,5 +88,5 @@ public IAutomationConsoleBuilder WithConfigurationMapping(IDictionary<string, st

public IAutomationConsole Build() => new AutomationConsoleApplication(rootCommand, args);

internal AutomationCommand GetRootCommand() => rootCommand;
internal AutomationRootCommand GetRootCommand() => rootCommand;
}
Loading