Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3742 was 3742, checked in by gkronber, 14 years ago

Fixed GPL license headers and deleted files which are not referenced by projects. #893

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