Free cookie consent management tool by TermsFeed Policy Generator

source: branches/New Persistence Exploration/Persistence/Persistence/Core/Serializer.cs @ 1362

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

Add serializer class information to type cache. (#506)

File size: 5.5 KB
Line 
1using System.Collections.Generic;
2using System.Collections;
3using System;
4using HeuristicLab.Persistence.Interfaces;
5
6namespace HeuristicLab.Persistence.Core {
7
8  public struct TypeMapping {
9    public readonly int Id;
10    public readonly string TypeName;
11    public readonly string Serializer;   
12    public TypeMapping(int id, string typeName, string serializer) {
13      Id = id;
14      TypeName = typeName;
15      Serializer = serializer;
16    }
17    public Dictionary<string, object> GetDict() {
18      return new Dictionary<string, object> {
19        {"id", Id},
20        {"typeName", TypeName},
21        {"serializer", Serializer}};                                           
22    }
23  }
24
25  public class Serializer : IEnumerable<ISerializationToken> {
26
27    private readonly object obj;
28    private readonly string rootName;
29    private readonly Dictionary<object, int> obj2id;
30    private readonly Dictionary<Type, int> typeCache;
31    private readonly Configuration configuration;
32
33    public List<TypeMapping> TypeCache {
34      get {       
35        List<TypeMapping> result = new List<TypeMapping>();
36        foreach (var pair in typeCache) {
37          string serializer = null;
38          IFormatter f = configuration.GetFormatter(pair.Key);
39          if (f != null) {
40            serializer = f.GetType().AssemblyQualifiedName;
41          } else {
42            IDecomposer d = configuration.GetDecomposer(pair.Key);
43            if (d != null)
44              serializer = d.GetType().AssemblyQualifiedName;
45          }
46          result.Add(new TypeMapping(pair.Value, pair.Key.AssemblyQualifiedName, serializer));
47        }
48        return result;                                     
49      }
50    }
51
52    public Serializer(object obj, Configuration configuration) :       
53      this(obj, configuration, "ROOT") { }
54
55    public Serializer(object obj, Configuration configuration, string rootName) {
56      this.obj = obj;
57      this.rootName = rootName;
58      this.configuration = configuration;     
59      obj2id = new Dictionary<object, int> {{new object(), 0}};
60      typeCache = new Dictionary<Type, int>();
61    }
62
63    IEnumerator IEnumerable.GetEnumerator() {
64      return GetEnumerator();
65    }
66
67    public IEnumerator<ISerializationToken> GetEnumerator() {
68      DataMemberAccessor rootAccessor = new DataMemberAccessor(
69        rootName, obj.GetType(), null, () => obj, null);
70      IEnumerator<ISerializationToken> iterator = Serialize(rootAccessor);
71      while (iterator.MoveNext())
72        yield return iterator.Current;     
73    }
74   
75    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
76      object value = accessor.Get();
77      if (value == null)
78        return NullReferenceEnumerator(accessor.Name);
79      if (obj2id.ContainsKey(value))
80        return ReferenceEnumerator(accessor.Name, obj2id[value]);             
81      if ( ! typeCache.ContainsKey(value.GetType()))
82        typeCache.Add(value.GetType(), typeCache.Count);
83      int typeId = typeCache[value.GetType()];
84      int? id = null;
85      if ( ! value.GetType().IsValueType) {
86        id = obj2id.Count;
87        obj2id.Add(value, (int)id);
88      }
89      IFormatter formatter = configuration.GetFormatter(value.GetType());
90      if (formatter != null)
91        return PrimitiveEnumerator(accessor.Name, typeId, formatter.DoFormat(value), id);
92      IDecomposer decomposer = configuration.GetDecomposer(value.GetType());
93      if (decomposer != null)
94        return CompositeEnumerator(accessor.Name, decomposer.DeCompose(value), id, typeId);           
95      return StorableEnumerator(accessor.Name, value, id, typeId);
96    }
97
98    private IEnumerator<ISerializationToken> NullReferenceEnumerator(string name) {
99      yield return new NullReferenceToken(name);
100    }
101
102    private IEnumerator<ISerializationToken> ReferenceEnumerator(string name, int id) {
103      yield return new ReferenceToken(name, id);
104    }
105
106    private IEnumerator<ISerializationToken> PrimitiveEnumerator(string name,
107        int typeId, object serializedValue, int? id) {
108      yield return new PrimitiveToken(name, typeId, serializedValue, id);
109    }
110
111    private IEnumerator<ISerializationToken> CompositeEnumerator(string name,
112        IEnumerable values, int? id, int typeId) {
113      yield return new BeginToken(name, typeId, id);     
114        foreach (object o in values) {
115          IEnumerator<ISerializationToken> iterator = Serialize(new DataMemberAccessor(o));
116          while (iterator.MoveNext())
117            yield return iterator.Current;
118        }
119      yield return new EndToken(name, typeId, id);       
120    }
121
122    private IEnumerator<ISerializationToken> StorableEnumerator(string name,
123        object value, int? id, int typeId) {           
124      yield return new BeginToken(name, typeId, id);
125      int nSubComponents = 0;
126      foreach (KeyValuePair<string, DataMemberAccessor> mapping in
127        StorableAttribute.GetAutostorableAccessors(value)) {
128        nSubComponents += 1;               
129        IEnumerator<ISerializationToken> iterator = Serialize(mapping.Value);
130        while (iterator.MoveNext()) {
131          yield return iterator.Current;
132        }
133      }
134      if (nSubComponents == 0) {
135        throw new ApplicationException(
136          String.Format(
137            "CustomComposite value of type \"{0}\" contains no subcomponents",
138            value.GetType().FullName));
139      }
140      yield return new EndToken(name, typeId, id);
141    }
142  }
143
144
145}
Note: See TracBrowser for help on using the repository browser.