Free cookie consent management tool by TermsFeed Policy Generator

source: branches/New Persistence Exploration/Persistence/Persistence/DeSerializer.cs @ 1318

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

added default constructor that includes all serializers of the persistence assembly. (#506)

File size: 6.5 KB
Line 
1using System.Collections.Generic;
2using System;
3namespace Persistence {
4  public class DeSerializer {
5
6    class ParentReference {     
7    }
8
9    delegate void Setter(object value);
10
11    interface IAccessibleObject {
12      object Obj { get; }     
13      Setter GetSetter(string name);
14    }
15
16    class CustomObject : IAccessibleObject {
17      public object Obj { get { return this.obj; } }
18      private object obj;
19      public List<object> customValues;
20      public CustomObject(object obj) {
21        this.obj = obj;
22        this.customValues = new List<object>();
23      }
24      public void AddValue(object value) {
25        customValues.Add(value);
26      }
27      public Setter GetSetter(string name) {
28        int index = customValues.Count-1;
29        return (value) => customValues[index] = value;
30      }
31    }
32
33    class CompositeObject : IAccessibleObject {
34      public object Obj { get { return this.obj; } }
35      public object obj;
36      public Dictionary<string, DataMemberAccessor> accessorDict;
37      public CompositeObject(object obj, Dictionary<string, DataMemberAccessor> accessorDict) {
38        this.obj = obj;
39        this.accessorDict = new Dictionary<string, DataMemberAccessor>();
40        foreach (KeyValuePair<string, DataMemberAccessor> pair in accessorDict) {
41          this.accessorDict.Add(
42            pair.Value.Name,
43            pair.Value);
44        }
45      }
46      public void SetValue(string name, object value) {
47        accessorDict[name].Set(value);
48      }
49      public void SetAllDefaultValues() {
50        throw new NotImplementedException();
51      }
52      public Setter GetSetter(string name) {
53        return (value) => accessorDict[name].Set(value);
54      }
55    }
56
57    private delegate void Handler(IParseToken token);
58
59    private Dictionary<int, object> id2obj;
60    private Dictionary<Type, Handler> handlers;
61    private Stack<IAccessibleObject> compositeStack;
62
63    private Dictionary<Type, IPrimitiveSerializer> primitiveSerializers;
64    private List<ICompoundSerializer> customSerializers;
65
66    delegate void Thunk();
67    private List<Thunk> finalFixes;
68
69    public DeSerializer() : this(
70      InterfaceInstantiatior.InstantiateAll<IPrimitiveSerializer>(),
71      InterfaceInstantiatior.InstantiateAll<ICompoundSerializer>()) {}   
72
73    public DeSerializer(
74        IEnumerable<IPrimitiveSerializer> primitiveSerializers,
75        IEnumerable<ICompoundSerializer> customSerializers) {
76      id2obj = new Dictionary<int, object>();
77      compositeStack = new Stack<IAccessibleObject>();
78      handlers = new Dictionary<Type, Handler>();
79      handlers.Add(typeof(CompositeStart), new Handler(CompositeStartHandler));
80      handlers.Add(typeof(CompositeEnd), new Handler(CompositeEndHandler));
81      handlers.Add(typeof(Primitive), new Handler(PrimitiveHandler));
82      handlers.Add(typeof(Reference), new Handler(ReferenceHandler));
83      handlers.Add(typeof(Null), new Handler(NullHandler));     
84      this.primitiveSerializers = new Dictionary<Type, IPrimitiveSerializer>();
85      foreach (IPrimitiveSerializer ps in primitiveSerializers) {
86        this.primitiveSerializers.Add(ps.Type, ps);
87      }
88      this.customSerializers = new List<ICompoundSerializer>(customSerializers);
89    }
90
91    public object DeSerialize(IEnumerable<IParseToken> tokens) {
92      this.finalFixes = new List<Thunk>();
93      foreach (IParseToken token in tokens) {
94        handlers[token.GetType()].Invoke(token);
95      }
96      foreach (Thunk fix in this.finalFixes) {
97        fix();
98      }
99      return compositeStack.Pop().Obj;
100    }
101
102    private void CompositeStartHandler(IParseToken token) {
103      CompositeStart start = (CompositeStart)token;
104      object instance = null;
105      if (this.FindCompoundSerializer(start.Type) != null) {
106        instance = new ParentReference();
107        compositeStack.Push(new CustomObject(instance));
108        id2obj.Add(start.Id, instance);       
109      } else {
110        instance = Activator.CreateInstance(start.Type);
111        Dictionary<string, DataMemberAccessor> accessorDict =
112        StorableAttribute.GetAutostorableAccessors(instance);
113        compositeStack.Push(new CompositeObject(instance, accessorDict));
114        id2obj.Add(start.Id, instance);
115      }
116    }
117    private void CompositeEndHandler(IParseToken token) {
118      CompositeEnd end = (CompositeEnd)token;
119      ICompoundSerializer customSerializer = this.FindCompoundSerializer(end.Type);
120      if (customSerializer != null) {
121        CustomObject customObject = (CustomObject)compositeStack.Pop();
122        object deserializedObject =
123          customSerializer.DeSerialize(customObject.customValues, end.Type);
124        this.id2obj[end.Id] = deserializedObject;       
125        this.SetValue(end.Name, deserializedObject);         
126      } else {
127        CompositeObject compositeObject = (CompositeObject)compositeStack.Pop();
128        this.SetValue(end.Name, compositeObject.obj);
129      }
130    }
131    private ICompoundSerializer FindCompoundSerializer(Type type) {
132      foreach (ICompoundSerializer serializer in customSerializers) {
133        if (serializer.CanSerialize(type))
134          return serializer;
135      }
136      return null;
137    }
138    private void PrimitiveHandler(IParseToken token) {
139      Primitive primitive = (Primitive)token;
140      object value = primitiveSerializers[primitive.Type].DeSerialize(primitive.SerializedValue);
141      this.SetValue(primitive.Name, value);
142    }
143    private void ReferenceHandler(IParseToken token) {
144      Reference reference = (Reference)token;
145      object referredObject = this.id2obj[reference.Id];
146      this.SetValue(reference.Name, this.id2obj[reference.Id]);
147      if (referredObject is ParentReference) {
148        Setter set = compositeStack.Peek().GetSetter(reference.Name);       
149        int id = reference.Id;
150        this.finalFixes.Add(() => set(id2obj[id]));
151      }
152    }
153    private void NullHandler(IParseToken token) {
154      Null nil = (Null)token;
155      this.SetValue(nil.Name, null);
156    }
157    private void SetValue(string name, object value) {
158      if (compositeStack.Count == 0) {
159        compositeStack.Push(new CompositeObject(value, new Dictionary<string, DataMemberAccessor>()));
160      } else {
161        object accessibleObject = compositeStack.Peek();
162        if (accessibleObject is CompositeObject) {
163          ((CompositeObject)accessibleObject).SetValue(name, value);
164        } else if (accessibleObject is CustomObject) {
165          ((CustomObject)accessibleObject).AddValue(value);
166        }
167      }
168    }
169  }
170}
Note: See TracBrowser for help on using the repository browser.