mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Add CliApplicationBuilder
This commit is contained in:
@@ -4,6 +4,10 @@ namespace CliFx.Tests.Dummy
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static Task<int> Main(string[] args) => new CliApplication().RunAsync(args);
|
||||
public static Task<int> Main(string[] args) =>
|
||||
new CliApplicationBuilder()
|
||||
.WithCommandsFromThisAssembly()
|
||||
.Build()
|
||||
.RunAsync(args);
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ namespace CliFx.Tests
|
||||
public async Task RunAsync_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
// Arrange
|
||||
var application = new CliApplication(commandTypes);
|
||||
var application = new CliApplicationBuilder().WithCommands(commandTypes).Build();
|
||||
|
||||
// Act
|
||||
var exitCodeValue = await application.RunAsync(commandLineArguments);
|
||||
@@ -218,7 +218,7 @@ namespace CliFx.Tests
|
||||
public async Task RunAsync_Negative_Test(IReadOnlyList<Type> commandTypes, IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
// Arrange
|
||||
var application = new CliApplication(commandTypes);
|
||||
var application = new CliApplicationBuilder().WithCommands(commandTypes).Build();
|
||||
|
||||
// Act
|
||||
var exitCodeValue = await application.RunAsync(commandLineArguments);
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Models;
|
||||
using CliFx.Services;
|
||||
|
||||
@@ -39,28 +36,6 @@ namespace CliFx
|
||||
_commandHelpTextRenderer = commandHelpTextRenderer;
|
||||
}
|
||||
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes, IConsole console)
|
||||
: this(applicationMetadata, commandTypes,
|
||||
console, new CommandInputParser(), new CommandSchemaResolver(),
|
||||
new CommandFactory(), new CommandInitializer(), new CommandHelpTextRenderer(console))
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication(ApplicationMetadata applicationMetadata, IReadOnlyList<Type> commandTypes)
|
||||
: this(applicationMetadata, commandTypes, new SystemConsole())
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication(IReadOnlyList<Type> commandTypes)
|
||||
: this(GetDefaultApplicationMetadata(), commandTypes)
|
||||
{
|
||||
}
|
||||
|
||||
public CliApplication()
|
||||
: this(GetDefaultCommandTypes())
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<int> RunAsync(IReadOnlyList<string> commandLineArguments)
|
||||
{
|
||||
try
|
||||
@@ -144,32 +119,6 @@ namespace CliFx
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CliApplication
|
||||
{
|
||||
private static ApplicationMetadata GetDefaultApplicationMetadata()
|
||||
{
|
||||
// Entry assembly is null in tests
|
||||
var entryAssembly = Assembly.GetEntryAssembly();
|
||||
|
||||
var title = entryAssembly?.GetName().Name ?? "App";
|
||||
var executableName = Path.GetFileNameWithoutExtension(entryAssembly?.Location) ?? "app";
|
||||
var versionText = entryAssembly?.GetName().Version.ToString() ?? "1.0";
|
||||
|
||||
return new ApplicationMetadata(title, executableName, versionText);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Type> GetDefaultCommandTypes()
|
||||
{
|
||||
// Entry assembly is null in tests
|
||||
var entryAssembly = Assembly.GetEntryAssembly();
|
||||
|
||||
if (entryAssembly == null)
|
||||
return Type.EmptyTypes;
|
||||
|
||||
return entryAssembly.ExportedTypes.Where(t => t.Implements(typeof(ICommand))).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CliApplication
|
||||
{
|
||||
[Command]
|
||||
|
||||
89
CliFx/CliApplicationBuilder.cs
Normal file
89
CliFx/CliApplicationBuilder.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Models;
|
||||
using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
public class CliApplicationBuilder : ICliApplicationBuilder
|
||||
{
|
||||
private readonly HashSet<Type> _commandTypes = new HashSet<Type>();
|
||||
|
||||
private string _title;
|
||||
private string _executableName;
|
||||
private string _versionText;
|
||||
private IConsole _console;
|
||||
private ICommandFactory _commandFactory;
|
||||
|
||||
public ICliApplicationBuilder WithCommand(Type commandType)
|
||||
{
|
||||
_commandTypes.Add(commandType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly)
|
||||
{
|
||||
var commandTypes = commandAssembly.ExportedTypes.Where(t => t.Implements(typeof(ICommand)));
|
||||
|
||||
foreach (var commandType in commandTypes)
|
||||
WithCommand(commandType);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseTitle(string title)
|
||||
{
|
||||
_title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseExecutableName(string exeName)
|
||||
{
|
||||
_executableName = exeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseVersionText(string version)
|
||||
{
|
||||
_versionText = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseConsole(IConsole console)
|
||||
{
|
||||
_console = console;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplicationBuilder UseCommandFactory(ICommandFactory factory)
|
||||
{
|
||||
_commandFactory = factory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICliApplication Build()
|
||||
{
|
||||
// Entry assembly is null in tests
|
||||
var entryAssembly = Assembly.GetEntryAssembly();
|
||||
|
||||
// Use defaults for required parameters that were not configured
|
||||
var title = _title ?? entryAssembly?.GetName().Name ?? "App";
|
||||
var executableName = _executableName ?? Path.GetFileNameWithoutExtension(entryAssembly?.Location) ?? "app";
|
||||
var versionText = _versionText ?? entryAssembly?.GetName().Version.ToString() ?? "1.0";
|
||||
var console = _console ?? new SystemConsole();
|
||||
var commandFactory = _commandFactory ?? new CommandFactory();
|
||||
|
||||
// Project parameters to expected types
|
||||
var applicationMetadata = new ApplicationMetadata(title, executableName, versionText);
|
||||
var commandTypes = _commandTypes.ToArray();
|
||||
|
||||
return new CliApplication(applicationMetadata, commandTypes,
|
||||
console, new CommandInputParser(), new CommandSchemaResolver(),
|
||||
commandFactory, new CommandInitializer(), new CommandHelpTextRenderer(console));
|
||||
}
|
||||
}
|
||||
}
|
||||
32
CliFx/Extensions.cs
Normal file
32
CliFx/Extensions.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static ICliApplicationBuilder WithCommands(this ICliApplicationBuilder builder, IReadOnlyList<Type> commandTypes)
|
||||
{
|
||||
foreach (var commandType in commandTypes)
|
||||
builder.WithCommand(commandType);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static ICliApplicationBuilder WithCommandsFrom(this ICliApplicationBuilder builder, IReadOnlyList<Assembly> commandAssemblies)
|
||||
{
|
||||
foreach (var commandAssembly in commandAssemblies)
|
||||
builder.WithCommandsFrom(commandAssembly);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static ICliApplicationBuilder WithCommandsFromThisAssembly(this ICliApplicationBuilder builder) =>
|
||||
builder.WithCommandsFrom(Assembly.GetCallingAssembly());
|
||||
|
||||
public static ICliApplicationBuilder UseCommandFactory(this ICliApplicationBuilder builder, Func<Type, ICommand> factoryMethod) =>
|
||||
builder.UseCommandFactory(new DelegateCommandFactory(factoryMethod));
|
||||
}
|
||||
}
|
||||
25
CliFx/ICliApplicationBuilder.cs
Normal file
25
CliFx/ICliApplicationBuilder.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using CliFx.Services;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
public interface ICliApplicationBuilder
|
||||
{
|
||||
ICliApplicationBuilder WithCommand(Type commandType);
|
||||
|
||||
ICliApplicationBuilder WithCommandsFrom(Assembly commandAssembly);
|
||||
|
||||
ICliApplicationBuilder UseTitle(string title);
|
||||
|
||||
ICliApplicationBuilder UseExecutableName(string exeName);
|
||||
|
||||
ICliApplicationBuilder UseVersionText(string version);
|
||||
|
||||
ICliApplicationBuilder UseConsole(IConsole console);
|
||||
|
||||
ICliApplicationBuilder UseCommandFactory(ICommandFactory factory);
|
||||
|
||||
ICliApplication Build();
|
||||
}
|
||||
}
|
||||
16
CliFx/Services/DelegateCommandFactory.cs
Normal file
16
CliFx/Services/DelegateCommandFactory.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace CliFx.Services
|
||||
{
|
||||
public class DelegateCommandFactory : ICommandFactory
|
||||
{
|
||||
private readonly Func<Type, ICommand> _factoryMethod;
|
||||
|
||||
public DelegateCommandFactory(Func<Type, ICommand> factoryMethod)
|
||||
{
|
||||
_factoryMethod = factoryMethod;
|
||||
}
|
||||
|
||||
public ICommand CreateCommand(Type commandType) => _factoryMethod(commandType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user