mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Add extensibility point for injecting custom option converters
Closes #19
This commit is contained in:
@@ -31,6 +31,7 @@ namespace CliFx.Tests
|
||||
.UseDescription("test")
|
||||
.UseConsole(new VirtualConsole(TextWriter.Null))
|
||||
.UseCommandFactory(schema => (ICommand) Activator.CreateInstance(schema.Type))
|
||||
.UseCommandOptionInputConverter(new CommandOptionInputConverter())
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace CliFx
|
||||
private string _description;
|
||||
private IConsole _console;
|
||||
private ICommandFactory _commandFactory;
|
||||
private ICommandOptionInputConverter _commandOptionInputConverter;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder AddCommand(Type commandType)
|
||||
@@ -108,6 +109,13 @@ namespace CliFx
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplicationBuilder UseCommandOptionInputConverter(ICommandOptionInputConverter converter)
|
||||
{
|
||||
_commandOptionInputConverter = converter.GuardNotNull(nameof(converter));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICliApplication Build()
|
||||
{
|
||||
@@ -117,6 +125,7 @@ namespace CliFx
|
||||
_versionText = _versionText ?? GetDefaultVersionText() ?? "v1.0";
|
||||
_console = _console ?? new SystemConsole();
|
||||
_commandFactory = _commandFactory ?? new CommandFactory();
|
||||
_commandOptionInputConverter = _commandOptionInputConverter ?? new CommandOptionInputConverter();
|
||||
|
||||
// Project parameters to expected types
|
||||
var metadata = new ApplicationMetadata(_title, _executableName, _versionText, _description);
|
||||
@@ -124,7 +133,7 @@ namespace CliFx
|
||||
|
||||
return new CliApplication(metadata, configuration,
|
||||
_console, new CommandInputParser(), new CommandSchemaResolver(),
|
||||
_commandFactory, new CommandInitializer(), new HelpTextRenderer());
|
||||
_commandFactory, new CommandInitializer(_commandOptionInputConverter), new HelpTextRenderer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace CliFx
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseCommandFactory(ICommandFactory factory);
|
||||
|
||||
/// <summary>
|
||||
/// Configures application to use specified implementation of <see cref="ICommandOptionInputConverter"/>.
|
||||
/// </summary>
|
||||
ICliApplicationBuilder UseCommandOptionInputConverter(ICommandOptionInputConverter converter);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="ICliApplication"/> using configured parameters.
|
||||
/// Default values are used in place of parameters that were not specified.
|
||||
|
||||
@@ -31,8 +31,13 @@ namespace CliFx.Services
|
||||
{
|
||||
}
|
||||
|
||||
private object ConvertValue(string value, Type targetType)
|
||||
/// <summary>
|
||||
/// Converts a single string value to specified target type.
|
||||
/// </summary>
|
||||
protected virtual object ConvertValue(string value, Type targetType)
|
||||
{
|
||||
targetType.GuardNotNull(nameof(targetType));
|
||||
|
||||
try
|
||||
{
|
||||
// String or object
|
||||
@@ -126,17 +131,19 @@ namespace CliFx.Services
|
||||
var parseMethod = GetStaticParseMethod(targetType);
|
||||
if (parseMethod != null)
|
||||
return parseMethod.Invoke(null, new object[] {value});
|
||||
|
||||
throw new CliFxException($"Can't convert value [{value}] to type [{targetType}].");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// An exception was thrown when trying to convert the value
|
||||
throw new CliFxException($"Can't convert value [{value}] to type [{targetType}].", ex);
|
||||
}
|
||||
|
||||
// Couldn't find a way to convert the value
|
||||
throw new CliFxException($"Can't convert value [{value}] to type [{targetType}].");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertOptionInput(CommandOptionInput optionInput, Type targetType)
|
||||
public virtual object ConvertOptionInput(CommandOptionInput optionInput, Type targetType)
|
||||
{
|
||||
optionInput.GuardNotNull(nameof(optionInput));
|
||||
targetType.GuardNotNull(nameof(targetType));
|
||||
|
||||
28
Readme.md
28
Readme.md
@@ -127,6 +127,34 @@ When resolving options, CliFx can convert string values obtained from the comman
|
||||
|
||||
If you want to define an option of your own type, the easiest way to do it is to make sure that your type is string-initializable, as explained above.
|
||||
|
||||
It is also possible to configure the application to use your own converter, by calling `UseCommandOptionInputConverter` method on `CliApplicationBuilder`.
|
||||
|
||||
```c#
|
||||
var app = new CliApplicationBuilder()
|
||||
.AddCommandsFromThisAssembly()
|
||||
.UseCommandOptionInputConverter(new MyConverter())
|
||||
.Build();
|
||||
```
|
||||
|
||||
The converter class must implement `ICommandOptionInputConverter` but you can also derive from `CommandOptionInputConverter` to extend the default behavior.
|
||||
|
||||
```c#
|
||||
public class MyConverter : CommandOptionInputConverter
|
||||
{
|
||||
protected override object ConvertValue(string value, Type targetType)
|
||||
{
|
||||
// Custom conversion for MyType
|
||||
if (targetType == typeof(MyType))
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// Default behavior for other types
|
||||
return base.ConvertValue(value, targetType);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Reporting errors
|
||||
|
||||
You may have noticed that commands in CliFx don't return exit codes. This is by design as exit codes are considered a higher-level concern and thus handled by `CliApplication`, not by individual commands.
|
||||
|
||||
Reference in New Issue
Block a user