Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/Core/DeSerializer.cs @ 1504

Last change on this file since 1504 was 1494, checked in by epitzer, 16 years ago

Generic decomposers for number arrays and number enumerables that "decompose" into a single string. (#563)

File size: 5.4 KB
Line 
1using System.Collections.Generic;
2using System;
3using HeuristicLab.Persistence.Interfaces;
4
5namespace HeuristicLab.Persistence.Core { 
6
7  public struct ParentReference {} 
8
9  class CompositeObject {
10
11    public object Obj { get; private set; }
12    public List<Tag> customValues;
13
14    public CompositeObject(object obj) {
15      Obj = obj;
16      customValues = new List<Tag>();
17    }
18
19    public void AddValue(string name, object value, List<Thunk> finalFixes) {
20      Tag t = new Tag(name, value) {finalFixes = finalFixes};
21      customValues.Add(t);
22    }
23
24    public Setter GetSetterForLastAddedValue(string name) {           
25      Tag t = customValues[customValues.Count - 1];     
26      return value => t.Value = value;
27    }
28  }
29
30  public delegate void Thunk();
31
32  public class DeSerializer {
33   
34    private readonly Dictionary<int, object> id2obj;
35    private readonly Dictionary<Type, object> serializerMapping;   
36    private readonly Stack<CompositeObject> parentStack;   
37    private readonly Dictionary<int, Type> typeIds;   
38    private List<Thunk> finalFixes;
39
40    public DeSerializer(
41      IEnumerable<TypeMapping> typeCache) {     
42      id2obj = new Dictionary<int, object>();
43      parentStack = new Stack<CompositeObject>();
44      typeIds = new Dictionary<int, Type>();
45      serializerMapping = createSerializers(typeCache);
46    }
47
48    private Dictionary<Type, object> createSerializers(IEnumerable<TypeMapping> typeCache) {
49      var map = new Dictionary<Type, object>();
50      foreach (var typeMapping in typeCache) {
51        Type type = Type.GetType(typeMapping.TypeName, true);
52        typeIds.Add(typeMapping.Id, type);
53        if (typeMapping.Serializer != null) {
54          Type serializerType = Type.GetType(typeMapping.Serializer);
55          map.Add(type, Activator.CreateInstance(serializerType, true));
56        }
57      }
58      return map;
59    }
60
61    public object DeSerialize(IEnumerable<ISerializationToken> tokens) {
62      finalFixes = new List<Thunk>();     
63      foreach (ISerializationToken token in tokens) {
64        Type t = token.GetType();
65        if ( t == typeof(BeginToken) ) {
66          CompositeStartHandler((BeginToken)token);
67        } else if ( t == typeof(EndToken) ) {
68          CompositeEndHandler((EndToken) token);
69        } else if ( t == typeof(PrimitiveToken) ) {
70          PrimitiveHandler((PrimitiveToken) token);
71        } else if ( t == typeof(ReferenceToken) ) {
72          ReferenceHandler((ReferenceToken) token);
73        } else if (t == typeof(NullReferenceToken)) {
74          NullHandler((NullReferenceToken)token);
75        } else {
76          throw new ApplicationException("invalid token type");
77        }
78      }
79      foreach (Thunk fix in finalFixes) {
80        fix();
81      }
82      return parentStack.Pop().Obj;
83    }
84
85    private void CompositeStartHandler(BeginToken token) {     
86      Type type = typeIds[(int)token.TypeId];
87      IDecomposer decomposer = null;
88      if ( serializerMapping.ContainsKey(type) )
89        decomposer = serializerMapping[type] as IDecomposer;     
90      if (decomposer == null)
91        throw new ApplicationException(String.Format(
92          "No suitable method for deserialization of type \"{0}\" found.",
93          type.VersionInvariantName()));
94      object instance =
95        decomposer.CreateInstance(type) ??
96        new ParentReference();
97      parentStack.Push(new CompositeObject(instance));             
98      if ( token.Id != null )
99        id2obj.Add((int)token.Id, instance);
100    }
101
102    private void CompositeEndHandler(EndToken token) {     
103      Type type = typeIds[(int)token.TypeId];
104      IDecomposer decomposer = null;
105      if (serializerMapping.ContainsKey(type))
106        decomposer = serializerMapping[type] as IDecomposer;           
107      if (decomposer == null)
108        throw new ApplicationException(String.Format(
109          "No suitable method for deserialization of type \"{0}\" found.",
110          type.VersionInvariantName()));
111      CompositeObject customComposite = parentStack.Pop();
112      object deserializedObject =         
113        decomposer.Populate(customComposite.Obj, customComposite.customValues, type);
114      if ( token.Id != null )
115        id2obj[(int)token.Id] = deserializedObject;       
116      SetValue(token.Name, deserializedObject);         
117    }
118
119    private void PrimitiveHandler(PrimitiveToken token) {     
120      Type type = typeIds[(int)token.TypeId];
121      object value = ((IFormatter) serializerMapping[type]).Parse(token.SerialData);
122      if ( token.Id != null )     
123        id2obj[(int)token.Id] = value;
124      SetValue(token.Name, value);
125    }
126
127    private void ReferenceHandler(ReferenceToken token) {     
128      object referredObject = id2obj[token.Id];
129      SetValue(token.Name, referredObject);     
130      if (referredObject is ParentReference) {
131        Setter set = parentStack.Peek().GetSetterForLastAddedValue(token.Name);               
132        finalFixes.Add(() => set(id2obj[token.Id]));
133      }
134    }
135
136    private void NullHandler(NullReferenceToken token) {     
137      SetValue(token.Name, null);
138    }   
139
140    private void SetValue(string name, object value) {
141      if (parentStack.Count == 0) {       
142        parentStack.Push(new CompositeObject(value));
143      } else {       
144        parentStack.Peek().AddValue(name, value, finalFixes);       
145      }
146    }
147  }
148}
Note: See TracBrowser for help on using the repository browser.