diff --git a/CliFx.Tests/CommandOptionInputConverterTests.cs b/CliFx.Tests/CommandOptionInputConverterTests.cs index 878565c..6eb8755 100644 --- a/CliFx.Tests/CommandOptionInputConverterTests.cs +++ b/CliFx.Tests/CommandOptionInputConverterTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using CliFx.Models; using CliFx.Services; using FluentAssertions; @@ -10,14 +11,14 @@ namespace CliFx.Tests { public partial class CommandOptionInputConverterTests { - public enum TestEnum + private enum TestEnum { Value1, Value2, Value3 } - public struct TestStringConstructable + private class TestStringConstructable { public string Value { get; } @@ -27,7 +28,7 @@ namespace CliFx.Tests } } - public struct TestStringParseable + private class TestStringParseable { public string Value { get; } @@ -38,6 +39,19 @@ namespace CliFx.Tests public static TestStringParseable Parse(string value) => new TestStringParseable(value); } + + private class TestStringParseableWithFormatProvider + { + public string Value { get; } + + private TestStringParseableWithFormatProvider(string value) + { + Value = value; + } + + public static TestStringParseableWithFormatProvider Parse(string value, IFormatProvider formatProvider) => + new TestStringParseableWithFormatProvider(value); + } } [TestFixture] @@ -159,6 +173,12 @@ namespace CliFx.Tests TestStringParseable.Parse("value") ); + yield return new TestCaseData( + new CommandOptionInput("option", "value"), + typeof(TestStringParseableWithFormatProvider), + TestStringParseableWithFormatProvider.Parse("value", CultureInfo.InvariantCulture) + ); + yield return new TestCaseData( new CommandOptionInput("option", new[] {"value1", "value2"}), typeof(string[]), diff --git a/CliFx/Services/CommandOptionInputConverter.cs b/CliFx/Services/CommandOptionInputConverter.cs index 75bafbc..ac8e9f8 100644 --- a/CliFx/Services/CommandOptionInputConverter.cs +++ b/CliFx/Services/CommandOptionInputConverter.cs @@ -22,6 +22,14 @@ namespace CliFx.Services { } + private ConstructorInfo GetStringConstructor(Type type) => type.GetConstructor(new[] {typeof(string)}); + + private MethodInfo GetStaticParseMethod(Type type) => + type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof(string)}, null); + + private MethodInfo GetStaticParseMethodWithFormatProvider(Type type) => + type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof(string), typeof(IFormatProvider)}, null); + private object ConvertValue(string value, Type targetType) { // String or object @@ -199,14 +207,21 @@ namespace CliFx.Services } // Has a constructor that accepts a single string - var stringConstructor = targetType.GetConstructor(new[] {typeof(string)}); + var stringConstructor = GetStringConstructor(targetType); if (stringConstructor != null) { return stringConstructor.Invoke(new object[] {value}); } + // Has a static parse method that accepts a single string and a format provider + var parseMethodWithFormatProvider = GetStaticParseMethodWithFormatProvider(targetType); + if (parseMethodWithFormatProvider != null) + { + return parseMethodWithFormatProvider.Invoke(null, new object[] { value, _formatProvider }); + } + // Has a static parse method that accepts a single string - var parseMethod = targetType.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new[] {typeof(string)}, null); + var parseMethod = GetStaticParseMethod(targetType); if (parseMethod != null) { return parseMethod.Invoke(null, new object[] {value});