Free cookie consent management tool by TermsFeed Policy Generator

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

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

Implement missing primitive formatter for char and add more comprehensive tests. (#548)

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