Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Number2StringSerializer.cs @ 3036

Last change on this file since 3036 was 3036, checked in by epitzer, 14 years ago

make most serializers internal and complete API documentation (#548)

File size: 6.6 KB
Line 
1using System;
2using System.Linq;
3using HeuristicLab.Persistence.Interfaces;
4using HeuristicLab.Persistence.Core;
5using HeuristicLab.Persistence.Auxiliary;
6using System.Collections.Generic;
7using System.Reflection;
8using System.Globalization;
9using System.Text;
10using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
11
12namespace HeuristicLab.Persistence.Default.CompositeSerializers {
13
14  /// <summary>
15  /// Serializes a primitive number type using the ToString() method and an
16  /// approriate precision and parses back the generated string using
17  /// the number type's Parse() method.
18  ///
19  /// This serializer has Priorty below zero and is disabled by default
20  /// but can be useful in generating custom serializers.
21  /// </summary>
22  [StorableClass]
23  public sealed class Number2StringSerializer : ICompositeSerializer {
24
25    private static readonly List<Type> numberTypes =
26      new List<Type> {
27        typeof(bool),
28        typeof(byte),
29        typeof(sbyte),
30        typeof(short),
31        typeof(ushort),
32        typeof(int),
33        typeof(uint),
34        typeof(long),
35        typeof(ulong),
36        typeof(float),
37        typeof(double),
38        typeof(decimal),
39      };
40
41    private static readonly Dictionary<Type, MethodInfo> numberParsers;
42
43    static Number2StringSerializer() {
44      numberParsers = new Dictionary<Type, MethodInfo>();
45      foreach (var type in numberTypes) {
46        numberParsers[type] = type
47          .GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
48                     null, new[] { typeof(string) }, null);
49      }
50    }
51
52    /// <summary>
53    /// Determines for every type whether the composite serializer is applicable.
54    /// </summary>
55    /// <param name="type">The type.</param>
56    /// <returns>
57    ///   <c>true</c> if this instance can serialize the specified type; otherwise, <c>false</c>.
58    /// </returns>
59    public bool CanSerialize(Type type) {
60      return numberParsers.ContainsKey(type);
61    }
62
63    /// <summary>
64    /// Give a reason if possibly why the given type cannot be serialized by this
65    /// ICompositeSerializer.
66    /// </summary>
67    /// <param name="type">The type.</param>
68    /// <returns>
69    /// A string justifying why type cannot be serialized.
70    /// </returns>
71    public string JustifyRejection(Type type) {
72      return string.Format("not a number type (one of {0})",
73        string.Join(", ", numberTypes.Select(n => n.Name).ToArray()));
74    }
75
76    /// <summary>
77    /// Formats the specified obj.
78    /// </summary>
79    /// <param name="obj">The obj.</param>
80    /// <returns></returns>
81    public string Format(object obj) {
82      if (obj.GetType() == typeof(float))
83        return ((float)obj).ToString("r", CultureInfo.InvariantCulture);
84      if (obj.GetType() == typeof(double))
85        return ((double)obj).ToString("r", CultureInfo.InvariantCulture);
86      if (obj.GetType() == typeof(decimal))
87        return ((decimal)obj).ToString("r", CultureInfo.InvariantCulture);
88      return obj.ToString();
89    }
90
91    /// <summary>
92    /// Parses the specified string value.
93    /// </summary>
94    /// <param name="stringValue">The string value.</param>
95    /// <param name="type">The type.</param>
96    /// <returns></returns>
97    public object Parse(string stringValue, Type type) {
98      try {
99        return numberParsers[type]
100          .Invoke(null,
101              BindingFlags.Static | BindingFlags.PutRefDispProperty,
102                    null, new[] { stringValue }, CultureInfo.InvariantCulture);
103      } catch (FormatException e) {
104        throw new PersistenceException("Invalid element data during number parsing.", e);
105      } catch (OverflowException e) {
106        throw new PersistenceException("Overflow during number parsing.", e);
107      }
108    }
109
110
111
112    /// <summary>
113    /// Defines the Priorty of this composite serializer. Higher number means
114    /// higher prioriy. Negative numbers are fallback serializers that are
115    /// disabled by default.
116    /// All default generic composite serializers have priority 100. Specializations
117    /// have priority 200 so they will  be tried first. Priorities are
118    /// only considered for default configurations.
119    /// </summary>
120    /// <value></value>
121    public int Priority {
122      get { return -100; }
123    }
124
125    /// <summary>
126    /// Generate MetaInfo necessary for instance creation. (e.g. dimensions
127    /// necessary for array creation.
128    /// </summary>
129    /// <param name="obj">An object.</param>
130    /// <returns>An enumerable of <see cref="Tag"/>s.</returns>
131    public IEnumerable<Tag> CreateMetaInfo(object obj) {
132      yield return new Tag(Format(obj));
133    }
134
135    /// <summary>
136    /// Decompose an object into <see cref="Tag"/>s, the tag name can be null,
137    /// the order in which elements are generated is guaranteed to be
138    /// the same as they will be supplied to the Populate method.
139    /// </summary>
140    /// <param name="obj">An object.</param>
141    /// <returns>An enumerable of <see cref="Tag"/>s.</returns>
142    public IEnumerable<Tag> Decompose(object obj) {
143      // numbers are composed just of meta info
144      return new Tag[] { };
145    }
146
147    /// <summary>
148    /// Create an instance of the object using the provided meta information.
149    /// </summary>
150    /// <param name="type">A type.</param>
151    /// <param name="metaInfo">The meta information.</param>
152    /// <returns>A fresh instance of the provided type.</returns>
153    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
154      var it = metaInfo.GetEnumerator();
155      try {
156        it.MoveNext();
157        return Parse((string)it.Current.Value, type);
158      } catch (InvalidOperationException e) {
159        throw new PersistenceException(
160          String.Format("Insufficient meta information to reconstruct number of type {0}.",
161          type.VersionInvariantName()), e);
162      } catch (InvalidCastException e) {
163        throw new PersistenceException("Invalid meta information element type", e);
164      }
165    }
166
167    /// <summary>
168    /// Fills an object with values from the previously generated <see cref="Tag"/>s
169    /// in Decompose. The order in which the values are supplied is
170    /// the same as they where generated. <see cref="Tag"/> names might be null.
171    /// </summary>
172    /// <param name="instance">An empty object instance.</param>
173    /// <param name="tags">The tags.</param>
174    /// <param name="type">The type.</param>
175    public void Populate(object instance, IEnumerable<Tag> tags, Type type) {
176      // numbers are composed just of meta info, no need to populate
177    }
178  }
179}
Note: See TracBrowser for help on using the repository browser.