#region Copyright 2009-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0 /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion using System; using System.Collections.Generic; namespace CSharpTest.Net.Utils { /// /// Handles the conversion of data to and from strings for serialization. Can /// alternatly be configured to provide other transforms for display or other /// outputs. /// public class StringConverter { /// /// The delegate type used to try and parse a string /// public delegate bool TryParseMethod(string text, out TYPE value); #region private class TypeConverter private interface IConvertToFromString { string ToString(object value); bool TryParse(string text, out object value); } private class ConvertToFromString : IConvertToFromString { public readonly TryParseMethod TryParse; bool IConvertToFromString.TryParse(string text, out object value) { TYPE data; if (TryParse(text, out data)) { value = data; return true; } else { value = null; return false; } } public new readonly Converter ToString; string IConvertToFromString.ToString(object value) { return ToString((TYPE)value); } public ConvertToFromString(TryParseMethod tryParse, Converter toString) { this.TryParse = tryParse; this.ToString = toString; } } #endregion private Dictionary _converters; /// /// Constructs a default StringConverter object for serialization /// public StringConverter() : this(true) {} /// /// Constructs a StringConverter optionally populated with the default /// serialization transforms. /// /// true to include default transforms public StringConverter(bool includeDefaults) { _converters = new Dictionary(); if (includeDefaults) AddDefaults(); } #region Default Converters private static string NormalToString(T value) { return value.ToString(); } //System.Single private static string SingleToString(Single value) { return value.ToString("r", System.Globalization.CultureInfo.InvariantCulture); } private static bool SingleTryParse(string value, out Single data) { return Single.TryParse(value, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowExponent | System.Globalization.NumberStyles.AllowLeadingSign, System.Globalization.CultureInfo.InvariantCulture, out data); } //System.Double private static string DoubleToString(Double value) { return value.ToString("r", System.Globalization.CultureInfo.InvariantCulture); } private static bool DoubleTryParse(string value, out Double data) { return Double.TryParse(value, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowExponent | System.Globalization.NumberStyles.AllowLeadingSign, System.Globalization.CultureInfo.InvariantCulture, out data); } //System.DateTime private static string DateTimeToString(DateTime date) { return date.ToString("o", System.Globalization.CultureInfo.InvariantCulture); } private static bool DateTimeTryParse(string value, out DateTime dt) { return DateTime.TryParseExact(value, "o", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind, out dt); } //System.Uri private static string UriToString(Uri value) { return value.AbsoluteUri; } private static bool UriTryParse(string value, out Uri uri) { return Uri.TryCreate(value, UriKind.Absolute, out uri); } //System.Guid private static bool StringTryParse(string value, out string data) { data = value; return data != null; } private static bool GuidTryParse(string value, out Guid data) { data = Guid.Empty; try { if (RegexPatterns.Guid.IsMatch(value)) { data = new Guid(value); return true; } } catch { } return false; } //System.Version private static bool VersionTryParse(string value, out Version data) { data = null; try { if (RegexPatterns.Version.IsMatch(value)) { data = new Version(value); return true; } } catch { } return false; } private void AddDefaults() { Add( bool.TryParse, NormalToString ); Add(byte.TryParse, NormalToString); Add(sbyte.TryParse, NormalToString); Add(char.TryParse, NormalToString); Add(DateTimeTryParse, DateTimeToString); Add(TimeSpan.TryParse, NormalToString); Add(decimal.TryParse, NormalToString); Add(DoubleTryParse, DoubleToString); Add(SingleTryParse, SingleToString); Add(GuidTryParse, NormalToString); Add(UriTryParse, UriToString); Add(short.TryParse, NormalToString); Add(ushort.TryParse, NormalToString); Add(int.TryParse, NormalToString); Add(uint.TryParse, NormalToString); Add(long.TryParse, NormalToString); Add(ulong.TryParse, NormalToString); Add(StringTryParse, NormalToString); Add(VersionTryParse, NormalToString); } #endregion /// /// Adds a converter for the type TYPE that can transform the TYPE to and from a string /// /// The type that can be transformed by the delegates /// A delegate method to convert from a string /// A delegate method to convert to a string public void Add(TryParseMethod tryParse, Converter toString) { _converters[typeof(TYPE)] = new ConvertToFromString(Check.NotNull(tryParse), Check.NotNull(toString)); } /// /// Removes the TYPE from the set of types allowed to be converted to and from strings. /// /// The type that will no longer be transformed public void Remove() { _converters.Remove(typeof(TYPE)); } /// /// Converts an object to a string if the type is registered, or ArgumentOutOfRangeException /// is thrown if no transform is registered for that type. /// public string ToString(object value) { IConvertToFromString cnvt; if (!_converters.TryGetValue(Check.NotNull(value).GetType(), out cnvt)) throw new ArgumentOutOfRangeException(Resources.StringConverterTryParse(value.GetType())); return cnvt.ToString(value); } /// /// Converts the value of TYPE to a string if the type is registered, or ArgumentOutOfRangeException /// is thrown if no transform is registered for that type. /// public string ToString(TYPE value) { IConvertToFromString cnvt; if (!_converters.TryGetValue(typeof(TYPE), out cnvt)) throw new ArgumentOutOfRangeException(Resources.StringConverterTryParse(typeof(TYPE))); return ((ConvertToFromString)cnvt).ToString(Check.NotNull(value)); } /// /// Converts the provided string to a value of TYPE if the type is registered, /// or raises ArgumentOutOfRangeException if no transform is registered for that type. /// Throws an ArgumentException if the string can not be converted. /// public TYPE FromString(string value) { TYPE data; if (!TryParse(Check.NotNull(value), out data)) throw new ArgumentException(); return data; } /// /// Converts the provided string to a value of TYPE if the type is registered, /// or raises ArgumentOutOfRangeException if no transform is registered for that type. /// /// The string value to convert /// The type of the value to be converted to /// The value once converted /// True if it was able to make the conversion public bool TryParse(string input, Type type, out object value) { if (input == null) { value = null; return false; } IConvertToFromString cnvt; if (!_converters.TryGetValue(Check.NotNull(type), out cnvt)) throw new ArgumentOutOfRangeException(Resources.StringConverterTryParse(type)); return cnvt.TryParse(Check.NotNull(input), out value); } /// /// Converts the provided string to a value of TYPE if the type is registered, /// or raises ArgumentOutOfRangeException if no transform is registered for that type. /// /// The type of the value to be converted to /// The string value to convert /// The value once converted /// True if it was able to make the conversion public bool TryParse(string input, out TYPE value) { if (input == null) { value = default(TYPE); return false; } IConvertToFromString cnvt; if (!_converters.TryGetValue(typeof(TYPE), out cnvt)) throw new ArgumentOutOfRangeException(Resources.StringConverterTryParse(typeof(TYPE))); return ((ConvertToFromString)cnvt).TryParse(Check.NotNull(input), out value); } } }