using System; using System.Linq; using HeuristicLab.Persistence.Interfaces; using HeuristicLab.Persistence.Core; using HeuristicLab.Persistence.Auxiliary; using System.Collections.Generic; using System.Reflection; using System.Globalization; using System.Text; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Persistence.Default.CompositeSerializers { [StorableClass(StorableClassType.Empty)] public class Number2StringSerializer : ICompositeSerializer { private static readonly List numberTypes = new List { typeof(bool), typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), }; private static readonly Dictionary numberParsers; static Number2StringSerializer() { numberParsers = new Dictionary(); foreach (var type in numberTypes) { numberParsers[type] = type .GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null); } } public bool CanSerialize(Type type) { return numberParsers.ContainsKey(type); } public string JustifyRejection(Type type) { return string.Format("not a number type (one of {0})", string.Join(", ", numberTypes.Select(n => n.Name).ToArray())); } public string Format(object obj) { if (obj.GetType() == typeof(float)) return ((float)obj).ToString("r", CultureInfo.InvariantCulture); if (obj.GetType() == typeof(double)) return ((double)obj).ToString("r", CultureInfo.InvariantCulture); if (obj.GetType() == typeof(decimal)) return ((decimal)obj).ToString("r", CultureInfo.InvariantCulture); return obj.ToString(); } public object Parse(string stringValue, Type type) { try { return numberParsers[type] .Invoke(null, BindingFlags.Static | BindingFlags.PutRefDispProperty, null, new[] { stringValue }, CultureInfo.InvariantCulture); } catch (FormatException e) { throw new PersistenceException("Invalid element data during number parsing.", e); } catch (OverflowException e) { throw new PersistenceException("Overflow during number parsing.", e); } } public int Priority { get { return -100; } } public IEnumerable CreateMetaInfo(object obj) { yield return new Tag(Format(obj)); } public IEnumerable Decompose(object obj) { // numbers are composed just of meta info return new Tag[] { }; } public object CreateInstance(Type type, IEnumerable metaInfo) { var it = metaInfo.GetEnumerator(); try { it.MoveNext(); return Parse((string)it.Current.Value, type); } catch (InvalidOperationException e) { throw new PersistenceException( String.Format("Insufficient meta information to reconstruct number of type {0}.", type.VersionInvariantName()), e); } catch (InvalidCastException e) { throw new PersistenceException("Invalid meta information element type", e); } } public void Populate(object instance, IEnumerable tags, Type type) { // numbers are composed just of meta info, no need to populate } } }