diff --git a/src/JSSoft.Commands/CommandContextBase.cs b/src/JSSoft.Commands/CommandContextBase.cs index 59026cd..44bd345 100644 --- a/src/JSSoft.Commands/CommandContextBase.cs +++ b/src/JSSoft.Commands/CommandContextBase.cs @@ -291,19 +291,19 @@ string GetVersionNames() } } - protected virtual void OnHelpExecute(string[] args) + protected virtual void OnHelpExecute(string[] args, CommandSettings settings) { - var items = args.Where(item => Settings.IsHelpArg(item) is false).ToArray(); + var items = args.Where(item => settings.IsHelpArg(item) is false).ToArray(); var helpCommand = HelpCommand; - var invoker = new InternalCommandInvoker(helpCommand); + var invoker = new InternalCommandInvoker(helpCommand, settings); invoker.Invoke(items); } - protected virtual void OnVersionExecute(string[] args) + protected virtual void OnVersionExecute(string[] args, CommandSettings settings) { - var items = args.Where(item => Settings.IsVersionArg(item) is false).ToArray(); + var items = args.Where(item => settings.IsVersionArg(item) is false).ToArray(); var versionCommand = VersionCommand; - var invoker = new InternalCommandInvoker(versionCommand); + var invoker = new InternalCommandInvoker(versionCommand, settings); invoker.Invoke(items); } @@ -411,21 +411,22 @@ where command.Parent is null private void ExecuteInternal(string[] args) { var argList = new List(args); + var settings = Settings; if (CommandUtility.IsEmptyArgs(args) is true) { OnEmptyExecute(); } - else if (Settings.ContainsHelpOption(args) is true) + else if (settings.ContainsHelpOption(args) is true) { - OnHelpExecute(args); + OnHelpExecute(args, settings); } - else if (Settings.ContainsVersionOption(args) is true) + else if (settings.ContainsVersionOption(args) is true) { - OnVersionExecute(args); + OnVersionExecute(args, settings); } else if (GetCommand(_commandNode, argList) is { } command) { - var invoker = new InternalCommandInvoker(command); + var invoker = new InternalCommandInvoker(command, settings); invoker.Invoke([.. argList]); } else @@ -438,21 +439,22 @@ private async Task ExecuteInternalAsync( string[] args, CancellationToken cancellationToken, IProgress progress) { var argList = new List(args); + var settings = Settings; if (CommandUtility.IsEmptyArgs(args) is true) { OnEmptyExecute(); } - else if (Settings.ContainsHelpOption(args) is true) + else if (settings.ContainsHelpOption(args) is true) { - OnHelpExecute(args); + OnHelpExecute(args, settings); } - else if (Settings.ContainsVersionOption(args) is true) + else if (settings.ContainsVersionOption(args) is true) { - OnVersionExecute(args); + OnVersionExecute(args, settings); } else if (GetCommand(_commandNode, argList) is { } command) { - var invoker = new InternalCommandInvoker(command); + var invoker = new InternalCommandInvoker(command, settings); await invoker.InvokeAsync([.. argList], cancellationToken, progress); } else @@ -461,8 +463,8 @@ private async Task ExecuteInternalAsync( } } - private sealed class InternalCommandInvoker(ICommand command) - : CommandInvoker(command.Name, command) + private sealed class InternalCommandInvoker(ICommand command, CommandSettings settings) + : CommandInvoker(command.Name, command, settings) { protected override void OnVerify(string[] args) { diff --git a/test/JSSoft.Commands.Tests/CommandContextTests/CommandAsICustomCommandDescriptor.cs b/test/JSSoft.Commands.Tests/CommandContextTests/CommandAsICustomCommandDescriptor.cs index a6437c3..54c0205 100644 --- a/test/JSSoft.Commands.Tests/CommandContextTests/CommandAsICustomCommandDescriptor.cs +++ b/test/JSSoft.Commands.Tests/CommandContextTests/CommandAsICustomCommandDescriptor.cs @@ -11,7 +11,7 @@ public class CommandAsICustomCommandDescriptor public void Test1() { var runCommand = new RunCommand(); - var commandContext = new TestCommandContext(runCommand); + var commandContext = new TestCommandContext([runCommand]); commandContext.Execute("run --string1 value1 --string2 value2"); diff --git a/test/JSSoft.Commands.Tests/CommandContextTests/CustomCommandTest.cs b/test/JSSoft.Commands.Tests/CommandContextTests/CustomCommandTest.cs index f93555d..e11b5f3 100644 --- a/test/JSSoft.Commands.Tests/CommandContextTests/CustomCommandTest.cs +++ b/test/JSSoft.Commands.Tests/CommandContextTests/CustomCommandTest.cs @@ -15,7 +15,7 @@ public void ExecutableNotImplemented_ThrowTest() { var customCommand = new CustomCommandWithoutExecutable(); Assert.Throws( - () => new TestCommandContext(customCommand)); + () => new TestCommandContext([customCommand])); } private sealed class CustomCommandWithoutExecutable : ICommand @@ -52,7 +52,7 @@ private sealed class CustomCommandWithoutExecutable : ICommand public void ExecutableImplemented_Test() { var customCommand = new CustomCommandWithExecutable(); - var commandContext = new TestCommandContext(customCommand); + var commandContext = new TestCommandContext([customCommand]); commandContext.Execute("test"); Assert.Equal(int.MaxValue, customCommand.Value); @@ -99,7 +99,7 @@ public void Execute() public async Task AsyncExecutableImplemented_TestAsync() { var customCommand = new CustomCommandWithAsyncExecutable(); - var commandContext = new TestCommandContext(customCommand); + var commandContext = new TestCommandContext([customCommand]); await commandContext.ExecuteAsync("test"); Assert.Equal(int.MaxValue, customCommand.Value); diff --git a/test/JSSoft.Commands.Tests/CommandContextTests/ServiceProviderTest.cs b/test/JSSoft.Commands.Tests/CommandContextTests/ServiceProviderTest.cs new file mode 100644 index 0000000..c23bfa8 --- /dev/null +++ b/test/JSSoft.Commands.Tests/CommandContextTests/ServiceProviderTest.cs @@ -0,0 +1,86 @@ +// +// Copyright (c) 2024 Jeesu Choi. All Rights Reserved. +// Licensed under the MIT License. See LICENSE.md in the project root for license information. +// + +using System.ComponentModel; +using System.Globalization; + +namespace JSSoft.Commands.Tests.CommandContextTests; + +public class ServiceProviderTest +{ + [Fact] + public void Execute_Test() + { + var testCommand = new TestCommand(); + var commands = new ICommand[] + { + testCommand, + }; + var settings = new CommandSettings + { + ServiceProvider = new ServiceProvider(), + }; + var commandContext = new TestCommandContext(settings, commands); + + commandContext.Execute("test --data 10"); + + Assert.Equal(11, testCommand.Data.Value); + } + + private sealed class TestCommand : CommandBase + { + [CommandProperty] + public Data Data { get; set; } + + protected override void OnExecute() + { + // do nothing + } + } + + [TypeConverter(typeof(DataTypeConverter))] + private struct Data + { + public int Value { get; set; } + } + + private sealed class DataTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + { + return sourceType == typeof(string); + } + + public override object? ConvertFrom( + ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + if (value is string text) + { + var i = int.Parse(text); + if (context is not null && context.GetService(typeof(int)) is int sum) + { + i += sum; + } + + return new Data() { Value = i }; + } + + return base.ConvertFrom(context, culture, value); + } + } + + private sealed class ServiceProvider : IServiceProvider + { + public object? GetService(Type serviceType) + { + if (serviceType == typeof(int)) + { + return 1; + } + + return null; + } + } +} diff --git a/test/JSSoft.Commands.Tests/CommandContextTests/TestCommandContext.cs b/test/JSSoft.Commands.Tests/CommandContextTests/TestCommandContext.cs index 8b9dddc..7131d30 100644 --- a/test/JSSoft.Commands.Tests/CommandContextTests/TestCommandContext.cs +++ b/test/JSSoft.Commands.Tests/CommandContextTests/TestCommandContext.cs @@ -5,7 +5,11 @@ namespace JSSoft.Commands.Tests.CommandContextTests; -public class TestCommandContext(params ICommand[] commands) - : CommandContextBase(commands) +public class TestCommandContext(CommandSettings settings, ICommand[] commands) + : CommandContextBase(commands, settings) { + public TestCommandContext(ICommand[] commands) + : this(CommandSettings.Default, commands) + { + } }