Free cookie consent management tool by TermsFeed Policy Generator

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

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

Namespace refactoring. (#548)

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