Free cookie consent management tool by TermsFeed Policy Generator

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

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

Replace final fixes for broken parent references with separation of instance creation with meta information. (#548)

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