mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Refactor
This commit is contained in:
@@ -1,33 +1,36 @@
|
||||
using System.Threading.Tasks;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Models;
|
||||
using CliFx.Services;
|
||||
using CliFx.Tests.TestObjects;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace CliFx.Tests
|
||||
{
|
||||
public partial class CliApplicationTests
|
||||
{
|
||||
[DefaultCommand]
|
||||
public class TestCommand : Command
|
||||
{
|
||||
public override ExitCode Execute() => new ExitCode(13);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class CliApplicationTests
|
||||
public partial class CliApplicationTests
|
||||
{
|
||||
[Test]
|
||||
public async Task RunAsync_Test()
|
||||
{
|
||||
// Arrange
|
||||
var command = new TestCommand();
|
||||
var expectedExitCode = await command.ExecuteAsync();
|
||||
|
||||
var commandOptionParser = new CommandOptionParser();
|
||||
|
||||
var typeProvider = new TypeProvider(typeof(TestCommand));
|
||||
var commandOptionConverter = new CommandOptionConverter();
|
||||
var commandResolver = new CommandResolver(typeProvider, commandOptionConverter);
|
||||
|
||||
var application = new CliApplication(commandOptionParser, commandResolver);
|
||||
var application = new CliApplication(
|
||||
new CommandOptionParser(),
|
||||
new CommandResolver(new[] {typeof(TestCommand)}, new CommandOptionConverter()));
|
||||
|
||||
// Act
|
||||
var exitCodeValue = await application.RunAsync();
|
||||
|
||||
// Assert
|
||||
Assert.That(exitCodeValue, Is.EqualTo(expectedExitCode.Value), "Exit code");
|
||||
Assert.That(exitCodeValue, Is.EqualTo(13), "Exit code");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,44 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using CliFx.Models;
|
||||
using CliFx.Services;
|
||||
using CliFx.Tests.TestObjects;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace CliFx.Tests
|
||||
{
|
||||
public partial class CommandOptionConverterTests
|
||||
{
|
||||
public enum TestEnum
|
||||
{
|
||||
Value1,
|
||||
Value2,
|
||||
Value3
|
||||
}
|
||||
|
||||
public struct TestStringConstructable
|
||||
{
|
||||
public string Value { get; }
|
||||
|
||||
public TestStringConstructable(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public struct TestStringParseable
|
||||
{
|
||||
public string Value { get; }
|
||||
|
||||
private TestStringParseable(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static TestStringParseable Parse(string value) => new TestStringParseable(value);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class CommandOptionConverterTests
|
||||
public partial class CommandOptionConverterTests
|
||||
{
|
||||
private static IEnumerable<TestCaseData> GetTestCases_ConvertOption()
|
||||
{
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Models;
|
||||
using CliFx.Services;
|
||||
using CliFx.Tests.TestObjects;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace CliFx.Tests
|
||||
{
|
||||
public partial class CommandResolverTests
|
||||
{
|
||||
[DefaultCommand]
|
||||
public class TestCommand : Command
|
||||
{
|
||||
[CommandOption("int", 'i', IsRequired = true)]
|
||||
public int IntOption { get; set; } = 24;
|
||||
|
||||
[CommandOption("str", 's')] public string StringOption { get; set; } = "foo bar";
|
||||
|
||||
public override ExitCode Execute() => new ExitCode(IntOption, StringOption);
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class CommandResolverTests
|
||||
public partial class CommandResolverTests
|
||||
{
|
||||
private static IEnumerable<TestCaseData> GetTestCases_ResolveCommand()
|
||||
{
|
||||
@@ -36,14 +50,6 @@ namespace CliFx.Tests
|
||||
}),
|
||||
new TestCommand {IntOption = 13}
|
||||
);
|
||||
|
||||
yield return new TestCaseData(
|
||||
new CommandOptionSet("command", new[]
|
||||
{
|
||||
new CommandOption("int", "13")
|
||||
}),
|
||||
new TestCommand {IntOption = 13}
|
||||
);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -51,10 +57,7 @@ namespace CliFx.Tests
|
||||
public void ResolveCommand_Test(CommandOptionSet commandOptionSet, TestCommand expectedCommand)
|
||||
{
|
||||
// Arrange
|
||||
var typeProvider = new TypeProvider(typeof(TestCommand));
|
||||
var optionConverter = new CommandOptionConverter();
|
||||
|
||||
var resolver = new CommandResolver(typeProvider, optionConverter);
|
||||
var resolver = new CommandResolver(new[] {typeof(TestCommand)}, new CommandOptionConverter());
|
||||
|
||||
// Act
|
||||
var command = resolver.ResolveCommand(commandOptionSet) as TestCommand;
|
||||
@@ -85,10 +88,7 @@ namespace CliFx.Tests
|
||||
public void ResolveCommand_IsRequired_Test(CommandOptionSet commandOptionSet)
|
||||
{
|
||||
// Arrange
|
||||
var typeProvider = new TypeProvider(typeof(TestCommand));
|
||||
var optionConverter = new CommandOptionConverter();
|
||||
|
||||
var resolver = new CommandResolver(typeProvider, optionConverter);
|
||||
var resolver = new CommandResolver(new[] {typeof(TestCommand)}, new CommandOptionConverter());
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<CommandResolveException>(() => resolver.ResolveCommand(commandOptionSet));
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Models;
|
||||
|
||||
namespace CliFx.Tests.TestObjects
|
||||
{
|
||||
[DefaultCommand]
|
||||
[Command("command")]
|
||||
public class TestCommand : Command
|
||||
{
|
||||
[CommandOption("int", 'i', IsRequired = true)]
|
||||
public int IntOption { get; set; } = 24;
|
||||
|
||||
[CommandOption("str", 's')]
|
||||
public string StringOption { get; set; } = "foo bar";
|
||||
|
||||
public override ExitCode Execute() => new ExitCode(IntOption, StringOption);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace CliFx.Tests.TestObjects
|
||||
{
|
||||
public enum TestEnum
|
||||
{
|
||||
Value1,
|
||||
Value2,
|
||||
Value3
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace CliFx.Tests.TestObjects
|
||||
{
|
||||
public struct TestStringConstructable
|
||||
{
|
||||
public string Value { get; }
|
||||
|
||||
public TestStringConstructable(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace CliFx.Tests.TestObjects
|
||||
{
|
||||
public partial struct TestStringParseable
|
||||
{
|
||||
public string Value { get; }
|
||||
|
||||
private TestStringParseable(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public partial struct TestStringParseable
|
||||
{
|
||||
public static TestStringParseable Parse(string value) => new TestStringParseable(value);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
public partial class CliApplication : ICliApplication
|
||||
public class CliApplication : ICliApplication
|
||||
{
|
||||
private readonly ICommandOptionParser _commandOptionParser;
|
||||
private readonly ICommandResolver _commandResolver;
|
||||
@@ -17,7 +16,7 @@ namespace CliFx
|
||||
}
|
||||
|
||||
public CliApplication()
|
||||
: this(new CommandOptionParser(), GetDefaultCommandResolver(Assembly.GetCallingAssembly()))
|
||||
: this(new CommandOptionParser(), new CommandResolver(new CommandOptionConverter()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -31,15 +30,4 @@ namespace CliFx
|
||||
return exitCode.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CliApplication
|
||||
{
|
||||
private static ICommandResolver GetDefaultCommandResolver(Assembly assembly)
|
||||
{
|
||||
var typeProvider = TypeProvider.FromAssembly(assembly);
|
||||
var commandOptionConverter = new CommandOptionConverter();
|
||||
|
||||
return new CommandResolver(typeProvider, commandOptionConverter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static Task<int> RunAsync(this ICliApplication application) =>
|
||||
application.RunAsync(Environment.GetCommandLineArgs().Skip(1).ToArray());
|
||||
public static Task<int> RunAsync(this ICliApplication application) => application.RunAsync(new string[0]);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ namespace CliFx.Internal
|
||||
// Derives from Command
|
||||
type.IsDerivedFrom(typeof(Command)) &&
|
||||
// Marked with DefaultCommandAttribute or CommandAttribute
|
||||
(type.IsDefined(typeof(DefaultCommandAttribute)) || type.IsDefined(typeof(CommandAttribute)));
|
||||
type.IsDefined(typeof(CommandAttribute));
|
||||
|
||||
public static CommandType Initialize(Type type)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Internal;
|
||||
@@ -8,18 +9,23 @@ using CliFx.Models;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
public class CommandResolver : ICommandResolver
|
||||
public partial class CommandResolver : ICommandResolver
|
||||
{
|
||||
private readonly ITypeProvider _typeProvider;
|
||||
private readonly IReadOnlyList<Type> _availableTypes;
|
||||
private readonly ICommandOptionConverter _commandOptionConverter;
|
||||
|
||||
public CommandResolver(ITypeProvider typeProvider, ICommandOptionConverter commandOptionConverter)
|
||||
public CommandResolver(IReadOnlyList<Type> availableTypes, ICommandOptionConverter commandOptionConverter)
|
||||
{
|
||||
_typeProvider = typeProvider;
|
||||
_availableTypes = availableTypes;
|
||||
_commandOptionConverter = commandOptionConverter;
|
||||
}
|
||||
|
||||
private IEnumerable<CommandType> GetCommandTypes() => CommandType.GetCommandTypes(_typeProvider.GetTypes());
|
||||
public CommandResolver(ICommandOptionConverter commandOptionConverter)
|
||||
: this(GetDefaultAvailableTypes(), commandOptionConverter)
|
||||
{
|
||||
}
|
||||
|
||||
private IEnumerable<CommandType> GetCommandTypes() => CommandType.GetCommandTypes(_availableTypes);
|
||||
|
||||
private CommandType GetDefaultCommandType()
|
||||
{
|
||||
@@ -100,4 +106,9 @@ namespace CliFx.Services
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CommandResolver
|
||||
{
|
||||
private static IReadOnlyList<Type> GetDefaultAvailableTypes() => Assembly.GetEntryAssembly()?.GetExportedTypes() ?? new Type[0];
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
public interface ITypeProvider
|
||||
{
|
||||
IReadOnlyList<Type> GetTypes();
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
public partial class TypeProvider : ITypeProvider
|
||||
{
|
||||
private readonly IReadOnlyList<Type> _types;
|
||||
|
||||
public TypeProvider(IReadOnlyList<Type> types)
|
||||
{
|
||||
_types = types;
|
||||
}
|
||||
|
||||
public TypeProvider(params Type[] types)
|
||||
: this((IReadOnlyList<Type>) types)
|
||||
{
|
||||
}
|
||||
|
||||
public IReadOnlyList<Type> GetTypes() => _types;
|
||||
}
|
||||
|
||||
public partial class TypeProvider
|
||||
{
|
||||
public static TypeProvider FromAssembly(Assembly assembly) => new TypeProvider(assembly.GetExportedTypes());
|
||||
|
||||
public static TypeProvider FromAssemblies(IReadOnlyList<Assembly> assemblies) =>
|
||||
new TypeProvider(assemblies.SelectMany(a => a.ExportedTypes).ToArray());
|
||||
|
||||
public static TypeProvider FromAssemblies(params Assembly[] assemblies) => FromAssemblies((IReadOnlyList<Assembly>) assemblies);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user