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

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

support composite value types (#506)

File size: 4.4 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, IPrimitiveSerializer> primitiveSerializers;
13    private readonly List<ICompoundSerializer> compoundSerializers;
14    private readonly Dictionary<Type, int> typeCache;
15
16    public Serializer(object obj) :
17      this(obj,
18      InterfaceInstantiatior.InstantiateAll<IPrimitiveSerializer>(),
19      InterfaceInstantiatior.InstantiateAll<ICompoundSerializer>()) {}
20
21    public Serializer(object obj,
22        IEnumerable<IPrimitiveSerializer> primitiveSerializers,
23        IEnumerable<ICompoundSerializer> compoundSerializers) :
24      this(obj, primitiveSerializers, compoundSerializers, "ROOT") { }
25
26    public Serializer(object obj,
27        IEnumerable<IPrimitiveSerializer> primitiveSerializers,
28        IEnumerable<ICompoundSerializer> compoundSerializers, string rootName) {
29      this.obj = obj;
30      this.rootName = rootName;
31      this.primitiveSerializers = new Dictionary<Type, IPrimitiveSerializer>();
32      foreach (IPrimitiveSerializer serializer in primitiveSerializers) {
33        this.primitiveSerializers.Add(serializer.Type, serializer);
34      }
35      this.compoundSerializers = new List<ICompoundSerializer>(compoundSerializers);
36      obj2id = new Dictionary<object, int> {{new object(), 0}};
37      typeCache = new Dictionary<Type, int>();
38    }
39
40    IEnumerator IEnumerable.GetEnumerator() {
41      return GetEnumerator();
42    }
43
44    public IEnumerator<ISerializationToken> GetEnumerator() {
45      DataMemberAccessor rootAccessor = new DataMemberAccessor(
46        rootName, obj.GetType(), null, () => obj, null);
47      IEnumerator<ISerializationToken> iterator = Serialize(rootAccessor);
48      while (iterator.MoveNext())
49        yield return iterator.Current;
50      Console.WriteLine("TypeCache:f");
51      foreach ( var pair in typeCache )
52        Console.WriteLine(pair.Key);
53    }
54
55    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
56
57      object value = accessor.Get();
58
59      if (value == null) {
60        yield return new NullReferenceToken(accessor.Name);
61        yield break;
62      }
63
64      if (obj2id.ContainsKey(value)) {
65        yield return new ReferenceToken(accessor.Name, obj2id[value]);
66        yield break;
67      }
68
69      if ( ! typeCache.ContainsKey(value.GetType()))
70        typeCache.Add(value.GetType(), typeCache.Count);
71
72      int? id = null;
73      if ( ! value.GetType().IsValueType) {
74        id = obj2id.Count;
75        obj2id.Add(value, (int)id);
76      }
77
78      if (primitiveSerializers.ContainsKey(value.GetType())) {
79       
80        yield return new PrimitiveToken(
81          accessor,
82          primitiveSerializers[value.GetType()].Serialize(value),
83          id);
84        yield break;
85      }
86     
87      yield return new BeginToken(accessor, id);
88      ICompoundSerializer customSerializer = FindCompoundSerializer(value.GetType());
89
90      if (customSerializer != null) {
91        foreach (object o in customSerializer.Serialize(value)) {
92          IEnumerator<ISerializationToken> iterator = Serialize(new DataMemberAccessor(o));
93          while (iterator.MoveNext())
94            yield return iterator.Current;
95        }
96        yield return new EndToken(accessor, id);
97        yield break;
98      }
99
100      int nSubComponents = 0;
101      foreach (KeyValuePair<string, DataMemberAccessor> mapping in
102        StorableAttribute.GetAutostorableAccessors(value)) {
103        nSubComponents += 1;
104        IEnumerator<ISerializationToken> iterator = Serialize(mapping.Value);
105        while (iterator.MoveNext()) {
106          yield return iterator.Current;
107        }
108      }
109      if (nSubComponents == 0) {
110        throw new ApplicationException(String.Format(
111                                         "Composite value of type \"{0}\" contains no subcomponents",
112                                         value.GetType().FullName));
113      }
114      yield return new EndToken(accessor, id);
115    }
116
117    private ICompoundSerializer FindCompoundSerializer(Type type) {
118      foreach (ICompoundSerializer s in compoundSerializers) {
119        if (s.CanSerialize(type))
120          return s;
121      }
122      return null;
123    }
124  }
125}
Note: See TracBrowser for help on using the repository browser.