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

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

Implement a type cache. (#506)

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