#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);
}
}
}