Free cookie consent management tool by TermsFeed Policy Generator

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

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

Unify token classes for parsing and formatting, make format specification mandatory. (#506)

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