Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4047 was 3811, checked in by epitzer, 15 years ago

correct and speed-up serialization for number enumerables (#548)

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