Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceReintegration/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/Number2StringSerializer.cs @ 15018

Last change on this file since 15018 was 15018, checked in by gkronber, 7 years ago

#2520 introduced StorableConstructorFlag type for StorableConstructors

File size: 7.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Persistence.Auxiliary;
26using HeuristicLab.Persistence.Core;
27using HeuristicLab.Persistence;
28using HeuristicLab.Persistence.Default.Xml;
29using HeuristicLab.Persistence.Default.Xml.Primitive;
30using HeuristicLab.Persistence.Interfaces;
31
32namespace HeuristicLab.Persistence.Default.CompositeSerializers {
33
34  /// <summary>
35  /// Serializes a primitive number type using the ToString() method and an
36  /// approriate precision and parses back the generated string using
37  /// the number type's Parse() method.
38  ///
39  /// This serializer has Priorty below zero and is disabled by default
40  /// but can be useful in generating custom serializers.
41  /// </summary>
42  [StorableType("23af67f5-2af6-4aca-b841-21345eacfb2f")]
43  public sealed class Number2StringSerializer : ICompositeSerializer {
44
45    [StorableConstructor]
46    private Number2StringSerializer(StorableConstructorFlag deserializing) { }
47    public Number2StringSerializer() { }
48
49    private static readonly Dictionary<Type, IPrimitiveSerializer> numberSerializerMap;
50    private static readonly List<IPrimitiveSerializer> numberSerializers = new List<IPrimitiveSerializer> {
51      new Bool2XmlSerializer(),
52      new Byte2XmlSerializer(),
53      new SByte2XmlSerializer(),
54      new Short2XmlSerializer(),
55      new UShort2XmlSerializer(),
56      new Int2XmlSerializer(),
57      new UInt2XmlSerializer(),
58      new Long2XmlSerializer(),
59      new ULong2XmlSerializer(),
60      new Float2XmlSerializer(),
61      new Double2XmlSerializer(),
62      new Decimal2XmlSerializer(),
63    };
64
65    static Number2StringSerializer() {
66      numberSerializerMap = new Dictionary<Type, IPrimitiveSerializer>();
67      foreach (var s in numberSerializers) {
68        numberSerializerMap[s.SourceType] = s;
69      }
70    }
71
72    /// <summary>
73    /// Determines for every type whether the composite serializer is applicable.
74    /// </summary>
75    /// <param name="type">The type.</param>
76    /// <returns>
77    ///   <c>true</c> if this instance can serialize the specified type; otherwise, <c>false</c>.
78    /// </returns>
79    public bool CanSerialize(Type type) {
80      return numberSerializerMap.ContainsKey(Nullable.GetUnderlyingType(type) ?? type);
81    }
82
83    /// <summary>
84    /// Give a reason if possibly why the given type cannot be serialized by this
85    /// ICompositeSerializer.
86    /// </summary>
87    /// <param name="type">The type.</param>
88    /// <returns>
89    /// A string justifying why type cannot be serialized.
90    /// </returns>
91    public string JustifyRejection(Type type) {
92      return string.Format("not a (nullable) number type (one of {0})",
93        string.Join(", ", numberSerializers.Select(n => n.SourceType.Name).ToArray()));
94    }
95
96    /// <summary>
97    /// Formats the specified obj.
98    /// </summary>
99    /// <param name="obj">The obj.</param>
100    /// <returns></returns>
101    public string Format(object obj) {
102      if (obj == null) return "null";
103      Type type = obj.GetType();
104      return ((XmlString)numberSerializerMap[Nullable.GetUnderlyingType(type) ?? type].Format(obj)).Data;
105    }
106
107    /// <summary>
108    /// Parses the specified string value.
109    /// </summary>
110    /// <param name="stringValue">The string value.</param>
111    /// <param name="type">The type.</param>
112    /// <returns></returns>
113    public object Parse(string stringValue, Type type) {
114      if (stringValue == "null") return null;
115      try {
116        return numberSerializerMap[Nullable.GetUnderlyingType(type) ?? type].Parse(new XmlString(stringValue));
117      } catch (FormatException e) {
118        throw new PersistenceException("Invalid element data during number parsing.", e);
119      } catch (OverflowException e) {
120        throw new PersistenceException("Overflow during number parsing.", e);
121      }
122    }
123
124
125
126    /// <summary>
127    /// Defines the Priorty of this composite serializer. Higher number means
128    /// higher prioriy. Negative numbers are fallback serializers that are
129    /// disabled by default.
130    /// All default generic composite serializers have priority 100. Specializations
131    /// have priority 200 so they will  be tried first. Priorities are
132    /// only considered for default configurations.
133    /// </summary>
134    /// <value></value>
135    public int Priority {
136      get { return -100; }
137    }
138
139    /// <summary>
140    /// Generate MetaInfo necessary for instance creation. (e.g. dimensions
141    /// necessary for array creation.
142    /// </summary>
143    /// <param name="obj">An object.</param>
144    /// <returns>An enumerable of <see cref="Tag"/>s.</returns>
145    public IEnumerable<Tag> CreateMetaInfo(object obj) {
146      yield return new Tag(Format(obj));
147    }
148
149    /// <summary>
150    /// Decompose an object into <see cref="Tag"/>s, the tag name can be null,
151    /// the order in which elements are generated is guaranteed to be
152    /// the same as they will be supplied to the Populate method.
153    /// </summary>
154    /// <param name="obj">An object.</param>
155    /// <returns>An enumerable of <see cref="Tag"/>s.</returns>
156    public IEnumerable<Tag> Decompose(object obj) {
157      // numbers are composed just of meta info
158      return new Tag[] { };
159    }
160
161    /// <summary>
162    /// Create an instance of the object using the provided meta information.
163    /// </summary>
164    /// <param name="type">A type.</param>
165    /// <param name="metaInfo">The meta information.</param>
166    /// <returns>A fresh instance of the provided type.</returns>
167    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
168      var it = metaInfo.GetEnumerator();
169      try {
170        it.MoveNext();
171        return Parse((string)it.Current.Value, type);
172      } catch (InvalidOperationException e) {
173        throw new PersistenceException(
174          String.Format("Insufficient meta information to reconstruct number of type {0}.",
175          type.VersionInvariantName()), e);
176      } catch (InvalidCastException e) {
177        throw new PersistenceException("Invalid meta information element type", e);
178      }
179    }
180
181    /// <summary>
182    /// Fills an object with values from the previously generated <see cref="Tag"/>s
183    /// in Decompose. The order in which the values are supplied is
184    /// the same as they where generated. <see cref="Tag"/> names might be null.
185    /// </summary>
186    /// <param name="instance">An empty object instance.</param>
187    /// <param name="tags">The tags.</param>
188    /// <param name="type">The type.</param>
189    public void Populate(object instance, IEnumerable<Tag> tags, Type type) {
190      // numbers are composed just of meta info, no need to populate
191    }
192  }
193}
Note: See TracBrowser for help on using the repository browser.