From 2ae980eb7e7a6280dd1081fd4160c5936cd03d5a Mon Sep 17 00:00:00 2001 From: andy Date: Sun, 29 Jul 2018 19:14:35 +0300 Subject: [PATCH] inputParser: support TypeConverters --- src/Oakton.Testing/InputParserTester.cs | 57 ++++++++++++++++++++++--- src/Oakton/Oakton.csproj | 1 + src/Oakton/Parsing/InputParser.cs | 21 ++++++++- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/Oakton.Testing/InputParserTester.cs b/src/Oakton.Testing/InputParserTester.cs index 20679ed8..d6c57739 100644 --- a/src/Oakton.Testing/InputParserTester.cs +++ b/src/Oakton.Testing/InputParserTester.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; using System.Linq.Expressions; using Baseline.Reflection; using Oakton.Help; @@ -377,9 +379,15 @@ public void use_dictionary_flag_for_dict() { handlerFor(x => x.PropsFlag).ShouldBeOfType(); } - - } + [Fact] + public void type_converters_can_be_used() + { + handle(x => x.Converted, "1234").ShouldBeTrue(); + + theInput.Converted.Value.ShouldBe(1234); + } + } public enum Color { @@ -410,9 +418,10 @@ public class InputModel [FlagAlias("aliased", 'a')] public string AliasedFlag { get; set; } - + public Dictionary PropsFlag { get; set; } = new Dictionary(); - + + public CustomID Converted { get; set; } } public class InputCommand : OaktonCommand @@ -428,4 +437,42 @@ public override bool Execute(InputModel input) throw new NotImplementedException(); } } -} \ No newline at end of file + + [TypeConverter(typeof(CustomIDConverter))] + public struct CustomID : IEquatable + { + public int Value { get; } + + public CustomID(int value) + { + Value = value; + } + + public bool Equals(CustomID other) => Value == other.Value; + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is CustomID && Equals((CustomID)obj); + } + + public override int GetHashCode() => Value; + public override string ToString() => Value.ToString(); + } + + public class CustomIDConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string == false) + return base.ConvertFrom(context, culture, value); + + return new CustomID(int.Parse((string)value)); + } + } +} diff --git a/src/Oakton/Oakton.csproj b/src/Oakton/Oakton.csproj index 701838b0..f12f74fb 100644 --- a/src/Oakton/Oakton.csproj +++ b/src/Oakton/Oakton.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Oakton/Parsing/InputParser.cs b/src/Oakton/Parsing/InputParser.cs index 438f2625..14ea454e 100644 --- a/src/Oakton/Parsing/InputParser.cs +++ b/src/Oakton/Parsing/InputParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; @@ -18,7 +19,13 @@ public static class InputParser private static readonly Regex SHORT_FLAG_REGEX = new Regex("^{0}[^-]+".ToFormat(SHORT_FLAG_PREFIX)); private static readonly string FLAG_SUFFIX = "Flag"; - private static readonly Conversions _converter = new Conversions(); + private static readonly Conversions _converter; + + static InputParser() + { + _converter = new Conversions(); + _converter.RegisterConversionProvider(); + } public static List GetHandlers(Type inputType) @@ -126,4 +133,16 @@ private static string splitOnPascalCaseAndAddHyphens(string name) return name.SplitPascalCase().Split(' ').Join("-"); } } + + public class TypeConverterProvider : IConversionProvider + { + public Func ConverterFor(Type type) + { + return value => + { + var converter = TypeDescriptor.GetConverter(type); + return converter.ConvertFromString(value); + }; + } + } } \ No newline at end of file