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

Last change on this file since 1349 was 1349, checked in by epitzer, 12 years ago

Central persistence configuration class. (#506)

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