Free cookie consent management tool by TermsFeed Policy Generator

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

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

Persistence fixes: Honor Storable.Name property, add more formatters and decomposers needed for HL integration. (#603)

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