mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 17:02:51 +08:00
Play nice with type converters
This commit is contained in:
parent
1dd1945297
commit
4d88a6ab69
@ -1,3 +1,6 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Spectre.Console.Cli;
|
using Spectre.Console.Cli;
|
||||||
@ -15,7 +18,8 @@ namespace Spectre.Console.Tests.Unit.Cli
|
|||||||
{
|
{
|
||||||
[CommandOption("-f|--foo <VALUE>")]
|
[CommandOption("-f|--foo <VALUE>")]
|
||||||
[IntegerValueProvider(32)]
|
[IntegerValueProvider(32)]
|
||||||
public int Foo { get; set; }
|
[TypeConverter(typeof(HexConverter))]
|
||||||
|
public string Foo { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class IntegerValueProvider : ParameterValueProviderAttribute
|
public sealed class IntegerValueProvider : ParameterValueProviderAttribute
|
||||||
@ -28,31 +32,40 @@ namespace Spectre.Console.Tests.Unit.Cli
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool TryGetValue(CommandParameterContext context, out object result)
|
public override bool TryGetValue(CommandParameterContext context, out object result)
|
||||||
{
|
|
||||||
if (context.Parameter.ParameterType == typeof(int))
|
|
||||||
{
|
{
|
||||||
if (context.Value == null)
|
if (context.Value == null)
|
||||||
{
|
{
|
||||||
result = _value;
|
result = _value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
result = null;
|
result = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class HexConverter : TypeConverter
|
||||||
|
{
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is int integer)
|
||||||
|
{
|
||||||
|
return integer.ToString("X");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value is string stringValue && int.TryParse(stringValue, out var intValue)
|
||||||
|
? intValue.ToString("X")
|
||||||
|
: base.ConvertFrom(context, culture, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_Use_Provided_Value_If_No_Value_Was_Specified()
|
public void Should_Use_Provided_Value_If_No_Value_Was_Specified()
|
||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
var app = new CommandAppTester();
|
var app = new CommandAppTester();
|
||||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||||
app.Configure(config =>
|
app.Configure(config => config.PropagateExceptions());
|
||||||
{
|
|
||||||
config.PropagateExceptions();
|
|
||||||
});
|
|
||||||
|
|
||||||
// When
|
// When
|
||||||
var result = app.Run();
|
var result = app.Run();
|
||||||
@ -60,7 +73,7 @@ namespace Spectre.Console.Tests.Unit.Cli
|
|||||||
// Then
|
// Then
|
||||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||||
{
|
{
|
||||||
settings.Foo.ShouldBe(32);
|
settings.Foo.ShouldBe("20"); // 32 is 0x20
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +83,7 @@ namespace Spectre.Console.Tests.Unit.Cli
|
|||||||
// Given
|
// Given
|
||||||
var app = new CommandAppTester();
|
var app = new CommandAppTester();
|
||||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||||
app.Configure(config =>
|
app.Configure(config => config.PropagateExceptions());
|
||||||
{
|
|
||||||
config.PropagateExceptions();
|
|
||||||
});
|
|
||||||
|
|
||||||
// When
|
// When
|
||||||
var result = app.Run("--foo", "12");
|
var result = app.Run("--foo", "12");
|
||||||
@ -81,7 +91,7 @@ namespace Spectre.Console.Tests.Unit.Cli
|
|||||||
// Then
|
// Then
|
||||||
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
result.Settings.ShouldBeOfType<ValueProviderSettings>().And(settings =>
|
||||||
{
|
{
|
||||||
settings.Foo.ShouldBe(12);
|
settings.Foo.ShouldBe("C"); // 12 is 0xC
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ namespace Spectre.Console.Cli
|
|||||||
var context = new CommandParameterContext(parameter, resolver, null);
|
var context = new CommandParameterContext(parameter, resolver, null);
|
||||||
if (parameter.ValueProvider.TryGetValue(context, out var result))
|
if (parameter.ValueProvider.TryGetValue(context, out var result))
|
||||||
{
|
{
|
||||||
|
result = ConvertValue(resolver, lookup, binder, parameter, result);
|
||||||
|
|
||||||
lookup.SetValue(parameter, result);
|
lookup.SetValue(parameter, result);
|
||||||
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
||||||
continue;
|
continue;
|
||||||
@ -42,16 +44,7 @@ namespace Spectre.Console.Cli
|
|||||||
if (parameter.DefaultValue != null)
|
if (parameter.DefaultValue != null)
|
||||||
{
|
{
|
||||||
var value = parameter.DefaultValue?.Value;
|
var value = parameter.DefaultValue?.Value;
|
||||||
|
value = ConvertValue(resolver, lookup, binder, parameter, value);
|
||||||
// Need to convert the default value?
|
|
||||||
if (value != null && value.GetType() != parameter.ParameterType)
|
|
||||||
{
|
|
||||||
var converter = GetConverter(lookup, binder, resolver, parameter);
|
|
||||||
if (converter != null)
|
|
||||||
{
|
|
||||||
value = converter.ConvertFrom(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binder.Bind(parameter, resolver, value);
|
binder.Bind(parameter, resolver, value);
|
||||||
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
||||||
@ -74,12 +67,6 @@ namespace Spectre.Console.Cli
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var converter = GetConverter(lookup, binder, resolver, mapped.Parameter);
|
|
||||||
if (converter == null)
|
|
||||||
{
|
|
||||||
throw CommandRuntimeException.NoConverterFound(mapped.Parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapped.Parameter.IsFlagValue() && mapped.Value == null)
|
if (mapped.Parameter.IsFlagValue() && mapped.Value == null)
|
||||||
{
|
{
|
||||||
if (mapped.Parameter is CommandOption option && option.DefaultValue != null)
|
if (mapped.Parameter is CommandOption option && option.DefaultValue != null)
|
||||||
@ -95,6 +82,12 @@ namespace Spectre.Console.Cli
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var converter = GetConverter(lookup, binder, resolver, mapped.Parameter);
|
||||||
|
if (converter == null)
|
||||||
|
{
|
||||||
|
throw CommandRuntimeException.NoConverterFound(mapped.Parameter);
|
||||||
|
}
|
||||||
|
|
||||||
// Assign the value to the parameter.
|
// Assign the value to the parameter.
|
||||||
binder.Bind(mapped.Parameter, resolver, converter.ConvertFromInvariantString(mapped.Value));
|
binder.Bind(mapped.Parameter, resolver, converter.ConvertFromInvariantString(mapped.Value));
|
||||||
}
|
}
|
||||||
@ -119,6 +112,20 @@ namespace Spectre.Console.Cli
|
|||||||
return lookup;
|
return lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object? ConvertValue(ITypeResolver resolver, CommandValueLookup lookup, CommandValueBinder binder, CommandParameter parameter, object? result)
|
||||||
|
{
|
||||||
|
if (result != null && result.GetType() != parameter.ParameterType)
|
||||||
|
{
|
||||||
|
var converter = GetConverter(lookup, binder, resolver, parameter);
|
||||||
|
if (converter != null)
|
||||||
|
{
|
||||||
|
result = converter.ConvertFrom(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "It's OK")]
|
[SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "It's OK")]
|
||||||
private static TypeConverter? GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter)
|
private static TypeConverter? GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user