source: branches/New Persistence Exploration/Persistence/Persistence/Serializer.cs @ 1357

Last change on this file since 1357 was 1357, checked in by epitzer, 11 years ago

Pluginification and major refactoring. (#506)

File size: 4.7 KB
Line 
1using System.Collections.Generic;
2using System.Collections;
3using System;
4using System.Linq;
5using HeuristicLab.Persistence.Interfaces;
6
7namespace HeuristicLab.Persistence {
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 PersistenceConfiguration persistenceConfiguration;
16
17    public Dictionary<string, int> TypeCache {
18      get {       
19        Dictionary<string, int> result = new Dictionary<string, int>();
20        foreach ( var pair in typeCache )
21          result.Add(pair.Key.AssemblyQualifiedName, pair.Value);
22        return result;                                     
23      }
24    }
25
26    public Serializer(object obj, PersistenceConfiguration persistenceConfiguration) :       
27      this(obj, persistenceConfiguration, "ROOT") { }
28
29    public Serializer(object obj, PersistenceConfiguration persistenceConfiguration, string rootName) {
30      this.obj = obj;
31      this.rootName = rootName;
32      this.persistenceConfiguration = persistenceConfiguration;     
33      obj2id = new Dictionary<object, int> {{new object(), 0}};
34      typeCache = new Dictionary<Type, int>();
35    }
36
37    IEnumerator IEnumerable.GetEnumerator() {
38      return GetEnumerator();
39    }
40
41    public IEnumerator<ISerializationToken> GetEnumerator() {
42      DataMemberAccessor rootAccessor = new DataMemberAccessor(
43        rootName, obj.GetType(), null, () => obj, null);
44      IEnumerator<ISerializationToken> iterator = Serialize(rootAccessor);
45      while (iterator.MoveNext())
46        yield return iterator.Current;     
47    }
48
49   
50    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
51      object value = accessor.Get();
52      if (value == null)
53        return NullReferenceEnumeration(accessor.Name);
54      if (obj2id.ContainsKey(value))
55        return ReferenceTokenEnumeration(accessor.Name, obj2id[value]);             
56      if ( ! typeCache.ContainsKey(value.GetType()))
57        typeCache.Add(value.GetType(), typeCache.Count);
58      int typeId = typeCache[value.GetType()];
59      int? id = null;
60      if ( ! value.GetType().IsValueType) {
61        id = obj2id.Count;
62        obj2id.Add(value, (int)id);
63      }
64      IFormatter formatter = persistenceConfiguration.GetFormatter(XmlFormat.Instance, value.GetType());
65      if (formatter != null)
66        return PrimitiveEnumeration(accessor.Name, typeId, formatter.Serialize(value), id);
67      IDecomposer decomposer = persistenceConfiguration.GetDecomposer(value.GetType()); 
68      if (decomposer != null)
69        return CompositeEnumeration(accessor.Name, decomposer.Serialize(value), id, typeId);           
70      return StorableEnumeration(accessor.Name, value, id, typeId);
71    }
72
73    private IEnumerator<ISerializationToken> NullReferenceEnumeration(string name) {
74      yield return new NullReferenceToken(name);
75    }
76
77    private IEnumerator<ISerializationToken> ReferenceTokenEnumeration(string name, int id) {
78      yield return new ReferenceToken(name, id);
79    }
80
81    private IEnumerator<ISerializationToken> PrimitiveEnumeration(string name, int typeId, object serializedValue, int? id) {
82      yield return new PrimitiveToken(name, typeId, serializedValue, id);
83    }
84
85    private IEnumerator<ISerializationToken> CompositeEnumeration(string name, IEnumerable values, int? id, int typeId) {
86      yield return new BeginToken(name, typeId, id);     
87        foreach (object o in values) {
88          IEnumerator<ISerializationToken> iterator = Serialize(new DataMemberAccessor(o));
89          while (iterator.MoveNext())
90            yield return iterator.Current;
91        }
92      yield return new EndToken(name, typeId, id);       
93    }
94
95    private IEnumerator<ISerializationToken> StorableEnumeration(string name, object value, int? id, int typeId) {           
96      yield return new BeginToken(name, typeId, id);
97      int nSubComponents = 0;
98      foreach (KeyValuePair<string, DataMemberAccessor> mapping in
99        StorableAttribute.GetAutostorableAccessors(value)) {
100        nSubComponents += 1;
101        IEnumerator<ISerializationToken> iterator = Serialize(mapping.Value);
102        while (iterator.MoveNext()) {
103          yield return iterator.Current;
104        }
105      }
106      if (nSubComponents == 0) {
107        throw new ApplicationException(String.Format(
108                                         "Composite value of type \"{0}\" contains no subcomponents",
109                                         value.GetType().FullName));
110      }
111      yield return new EndToken(name, typeId, id);
112    }
113  }
114
115
116}
Note: See TracBrowser for help on using the repository browser.