Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Core/Serializer.cs @ 1780

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

Store full version information with serialized data, only fall back to version invariant format if loading fails with full version. Also check, that loaded version is newer than requested version if possible. (#613)

File size: 5.3 KB
Line 
1using System.Collections.Generic;
2using System.Collections;
3using System;
4using System.Linq;
5using HeuristicLab.Persistence.Auxiliary;
6using HeuristicLab.Persistence.Interfaces;
7using HeuristicLab.Persistence.Core.Tokens;
8using HeuristicLab.Persistence.Default.Decomposers.Storable;
9using System.Text;
10
11namespace HeuristicLab.Persistence.Core {
12
13  public class Serializer : IEnumerable<ISerializationToken> {
14
15    class ReferenceEqualityComparer : IEqualityComparer<object> {
16
17      public bool Equals(object a, object b) {
18        return Object.ReferenceEquals(a, b);
19      }
20
21      public int GetHashCode(object obj) {
22        if (obj == null)
23          return 0;
24        return obj.GetHashCode();
25      }
26
27    }
28
29    private readonly object obj;
30    private readonly string rootName;
31    private readonly Dictionary<object, int> obj2id;
32    private readonly Dictionary<Type, int> typeCache;
33    private readonly Configuration configuration;
34
35    public List<TypeMapping> TypeCache {
36      get {
37        List<TypeMapping> result = new List<TypeMapping>();
38        foreach (var pair in typeCache) {
39          string serializer = null;
40          IFormatter f = configuration.GetFormatter(pair.Key);
41          if (f != null) {
42            serializer = f.GetType().AssemblyQualifiedName;
43          } else {
44            IDecomposer d = configuration.GetDecomposer(pair.Key);
45            serializer = d.GetType().AssemblyQualifiedName;
46          }
47          //result.Add(new TypeMapping(pair.Value, pair.Key.AssemblyQualifiedName, serializer));
48          result.Add(new TypeMapping(pair.Value, pair.Key.VersionInvariantName(), serializer));
49        }
50        return result;
51      }
52    }
53
54    public Serializer(object obj, Configuration configuration) :
55      this(obj, configuration, "ROOT") { }
56
57    public Serializer(object obj, Configuration configuration, string rootName) {
58      this.obj = obj;
59      this.rootName = rootName;
60      this.configuration = configuration;
61      obj2id = new Dictionary<object, int>(new ReferenceEqualityComparer()) { { new object(), 0 } };
62      typeCache = new Dictionary<Type, int>();
63    }
64
65    IEnumerator IEnumerable.GetEnumerator() {
66      return GetEnumerator();
67    }
68
69    public IEnumerator<ISerializationToken> GetEnumerator() {
70      return Serialize(new DataMemberAccessor(rootName, null, () => obj, null));
71    }
72
73    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
74      object value = accessor.Get();
75      if (value == null)
76        return NullReferenceEnumerator(accessor.Name);
77      Type type = value.GetType();
78      if (obj2id.ContainsKey(value))
79        return ReferenceEnumerator(accessor.Name, obj2id[value]);
80      if (!typeCache.ContainsKey(type))
81        typeCache.Add(type, typeCache.Count);
82      int typeId = typeCache[type];
83      int? id = null;
84      if (!type.IsValueType) {
85        id = obj2id.Count;
86        obj2id.Add(value, (int)id);
87      }
88      IFormatter formatter = configuration.GetFormatter(type);
89      if (formatter != null)
90        return PrimitiveEnumerator(accessor.Name, typeId, formatter.Format(value), id);
91      IDecomposer decomposer = configuration.GetDecomposer(type);
92      if (decomposer != null)
93        return CompositeEnumerator(accessor.Name, decomposer.Decompose(value), id, typeId, decomposer.CreateMetaInfo(value));
94      throw new PersistenceException(
95          String.Format(
96          "No suitable method for serializing values of type \"{0}\" found\r\n" +
97          "Formatters:\r\n{1}\r\n" +
98          "Decomposers:\r\n{2}",
99          value.GetType().VersionInvariantName(),
100          string.Join("\r\n", configuration.Formatters.Select(f => f.GetType().VersionInvariantName()).ToArray()),
101          string.Join("\r\n", configuration.Decomposers.Select(d => d.GetType().VersionInvariantName()).ToArray())
102          ));
103
104    }
105
106    private IEnumerator<ISerializationToken> NullReferenceEnumerator(string name) {
107      yield return new NullReferenceToken(name);
108    }
109
110    private IEnumerator<ISerializationToken> ReferenceEnumerator(string name, int id) {
111      yield return new ReferenceToken(name, id);
112    }
113
114    private IEnumerator<ISerializationToken> PrimitiveEnumerator(string name,
115        int typeId, ISerialData serializedValue, int? id) {
116      yield return new PrimitiveToken(name, typeId, id, serializedValue);
117    }
118
119    private IEnumerator<ISerializationToken> CompositeEnumerator(
120        string name, IEnumerable<Tag> tags, int? id, int typeId, IEnumerable<Tag> metaInfo) {
121      yield return new BeginToken(name, typeId, id);
122      bool first = true;
123      foreach (var tag in metaInfo) {
124        IEnumerator<ISerializationToken> metaIt = Serialize(new DataMemberAccessor(tag.Value, tag.Name));
125        while (metaIt.MoveNext()) {
126          if (first) {
127            yield return new MetaInfoBeginToken();
128            first = false;
129          }
130          yield return metaIt.Current;
131        }
132      }
133      if (!first) {
134        yield return new MetaInfoEndToken();
135      }
136      foreach (var tag in tags) {
137        IEnumerator<ISerializationToken> it = Serialize(new DataMemberAccessor(tag.Value, tag.Name));
138        while (it.MoveNext())
139          yield return it.Current;
140      }
141      yield return new EndToken(name, typeId, id);
142    }
143
144  }
145
146
147}
Note: See TracBrowser for help on using the repository browser.