mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 00:42: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 Shouldly;
|
||||
using Spectre.Console.Cli;
|
||||
@ -15,7 +18,8 @@ namespace Spectre.Console.Tests.Unit.Cli
|
||||
{
|
||||
[CommandOption("-f|--foo <VALUE>")]
|
||||
[IntegerValueProvider(32)]
|
||||
public int Foo { get; set; }
|
||||
[TypeConverter(typeof(HexConverter))]
|
||||
public string Foo { get; set; }
|
||||
}
|
||||
|
||||
public sealed class IntegerValueProvider : ParameterValueProviderAttribute
|
||||
@ -29,13 +33,10 @@ namespace Spectre.Console.Tests.Unit.Cli
|
||||
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
result = _value;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = null;
|
||||
@ -43,16 +44,28 @@ namespace Spectre.Console.Tests.Unit.Cli
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
public void Should_Use_Provided_Value_If_No_Value_Was_Specified()
|
||||
{
|
||||
// Given
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run();
|
||||
@ -60,7 +73,7 @@ namespace Spectre.Console.Tests.Unit.Cli
|
||||
// Then
|
||||
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
|
||||
var app = new CommandAppTester();
|
||||
app.SetDefaultCommand<GenericCommand<ValueProviderSettings>>();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.PropagateExceptions();
|
||||
});
|
||||
app.Configure(config => config.PropagateExceptions());
|
||||
|
||||
// When
|
||||
var result = app.Run("--foo", "12");
|
||||
@ -81,7 +91,7 @@ namespace Spectre.Console.Tests.Unit.Cli
|
||||
// Then
|
||||
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);
|
||||
if (parameter.ValueProvider.TryGetValue(context, out var result))
|
||||
{
|
||||
result = ConvertValue(resolver, lookup, binder, parameter, result);
|
||||
|
||||
lookup.SetValue(parameter, result);
|
||||
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
||||
continue;
|
||||
@ -42,16 +44,7 @@ namespace Spectre.Console.Cli
|
||||
if (parameter.DefaultValue != null)
|
||||
{
|
||||
var value = parameter.DefaultValue?.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);
|
||||
}
|
||||
}
|
||||
value = ConvertValue(resolver, lookup, binder, parameter, value);
|
||||
|
||||
binder.Bind(parameter, resolver, value);
|
||||
CommandValidator.ValidateParameter(parameter, lookup, resolver);
|
||||
@ -74,12 +67,6 @@ namespace Spectre.Console.Cli
|
||||
}
|
||||
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 is CommandOption option && option.DefaultValue != null)
|
||||
@ -95,6 +82,12 @@ namespace Spectre.Console.Cli
|
||||
}
|
||||
else
|
||||
{
|
||||
var converter = GetConverter(lookup, binder, resolver, mapped.Parameter);
|
||||
if (converter == null)
|
||||
{
|
||||
throw CommandRuntimeException.NoConverterFound(mapped.Parameter);
|
||||
}
|
||||
|
||||
// Assign the value to the parameter.
|
||||
binder.Bind(mapped.Parameter, resolver, converter.ConvertFromInvariantString(mapped.Value));
|
||||
}
|
||||
@ -119,6 +112,20 @@ namespace Spectre.Console.Cli
|
||||
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")]
|
||||
private static TypeConverter? GetConverter(CommandValueLookup lookup, CommandValueBinder binder, ITypeResolver resolver, CommandParameter parameter)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user