Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/06/09 14:36:10 (16 years ago)
Author:
epitzer
Message:

Complete serialisation/deserialization cycle. (#506)

Location:
branches/New Persistence Exploration/Persistence/Persistence
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • branches/New Persistence Exploration/Persistence/Persistence/NewSerializationTest.cs

    r1264 r1274  
    33using System.Text;
    44using System.Collections;
     5using System.IO;
    56
    67namespace Persistence {
     
    1415    [Storable]
    1516    public ArrayList intArray = new ArrayList(new int[] { 1, 2, 3 });
     17    [Storable]
     18    public List<int> intList = new List<int>(new int[] { 321, 312, 321 });
    1619    [Storable]
    1720    public Custom c;
     
    3841      Serializer s = new Serializer(r, serializers);
    3942      Persistence.XmlFormatter xmlFormatter = new Persistence.XmlFormatter();
     43      StreamWriter writer = new StreamWriter("test.xml");
    4044      foreach (ISerializationToken token in s) {
    41         Console.Write(xmlFormatter.Format(token));
     45        string line = xmlFormatter.Format(token);
     46        writer.Write(line);
     47        Console.Out.Write(line);
    4248      }
     49      writer.Close();
     50      XmlParser parser = new XmlParser(new StreamReader("test.xml"));
     51      DeSerializer deSerializer = new DeSerializer();     
     52      object o = deSerializer.DeSerialize(parser);
     53      Console.Out.WriteLine(Util.AutoFormat(o, true));
    4354      Console.In.ReadLine();
    4455    }
  • branches/New Persistence Exploration/Persistence/Persistence/Persistence.csproj

    r1264 r1274  
    4949  </ItemGroup>
    5050  <ItemGroup>
     51    <Compile Include="Util.cs" />
    5152    <Compile Include="StorableAttributeTests.cs" />
    5253    <Compile Include="StorableAttribute.cs" />
  • branches/New Persistence Exploration/Persistence/Persistence/PersistenceManager.cs

    r1264 r1274  
    55using System.Collections;
    66using System.Reflection;
     7using System.Xml;
    78
    89namespace Persistence {
     
    8586  #endregion
    8687
    87   #region Generics (incomplete)
     88  #region Custom
    8889  public interface ICustomSerializer {
    8990    bool CanSerialize(Type type);
     
    127128    }
    128129
    129     public object DeSerialize(IEnumerable o, Type t) {
    130       throw new NotImplementedException();
    131     }
    132 
    133   }
     130    public object DeSerialize(IEnumerable elements, Type t) {
     131      List<object> allElements = new List<object>();
     132      foreach (object obj in elements) {
     133        allElements.Add(obj);
     134      }
     135      Array array =
     136        Array.CreateInstance(t.GetElementType(), allElements.Count);
     137      for (int i = 0; i < array.Length; i++) {
     138        array.SetValue(allElements[i], i);
     139      }
     140      return array;
     141    }
     142
     143  } 
    134144  #endregion
    135145
     
    172182
    173183    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
    174       object value = accessor.Get();
     184      object value = accessor.Get();     
    175185      if (value == null) {
    176186        yield return new NullReferenceToken(accessor.Name);
    177       } else if (this.primitiveSerializers.ContainsKey(accessor.Type)) {
    178         yield return new PrimitiveToken(accessor, this.primitiveSerializers[accessor.Type].Serialize(value));
     187      } else if (this.primitiveSerializers.ContainsKey(value.GetType())) {
     188        yield return new PrimitiveToken(accessor, this.primitiveSerializers[value.GetType()].Serialize(value));
    179189      } else if (this.obj2id.ContainsKey(value)) {
    180190        yield return new ReferenceToken(accessor.Name, this.obj2id[value]);
     
    183193        this.obj2id.Add(value, id);
    184194        yield return new BeginToken(accessor, id);
    185         ICustomSerializer customSerializer = this.FindCustomSerializer(accessor.Type);
     195        ICustomSerializer customSerializer = this.FindCustomSerializer(value.GetType());
    186196        if (customSerializer != null) {
    187197          foreach (object obj in customSerializer.Serialize(value)) {
     
    200210        yield return new EndToken(accessor, id);       
    201211      }
    202     }
     212    }   
    203213
    204214    private ICustomSerializer FindCustomSerializer(Type type) {
     
    209219      return null;
    210220    }               
     221  }
     222
     223  public class DeSerializer {   
     224
     225    class AccessibleObject {
     226      public object obj;
     227      public Dictionary<string, DataMemberAccessor> accessorDict;
     228      public List<object> customValues;
     229      public AccessibleObject(object obj, Dictionary<string, DataMemberAccessor> accessorDict) {
     230        this.obj = obj;
     231        this.accessorDict = new Dictionary<string, DataMemberAccessor>();
     232        this.customValues = new List<object>();
     233        foreach (KeyValuePair<string, DataMemberAccessor> pair in accessorDict) {
     234          this.accessorDict.Add(
     235            pair.Value.Name,
     236            pair.Value);
     237        }
     238      }
     239      public void SetValue(string name, object value) {
     240        if (name == "") {
     241          customValues.Add(value);
     242        } else {
     243          accessorDict[name].Set(value);
     244        }
     245      }
     246      public void SetAllDefaultValues() {
     247      }
     248    }
     249
     250    private delegate void Handler(IParseToken token);
     251
     252    private Dictionary<int, object> id2obj;
     253    private Dictionary<Type, Handler> handlers;
     254    private Stack<AccessibleObject> compositeStack;   
     255
     256    private Dictionary<Type, IPrimitiveSerializer> primitiveSerializers;
     257    private List<ICustomSerializer> customSerializers;
     258
     259    public DeSerializer() {
     260      id2obj = new Dictionary<int, object>();
     261      compositeStack = new Stack<AccessibleObject>();
     262      handlers = new Dictionary<Type, Handler>();
     263      handlers.Add(typeof(CompositeStart), new Handler(CompositeStartHandler));
     264      handlers.Add(typeof(CompositeEnd), new Handler(CompositeEndHandler));
     265      handlers.Add(typeof(Primitive), new Handler(PrimitiveHandler));
     266      handlers.Add(typeof(Reference), new Handler(ReferenceHandler));
     267      handlers.Add(typeof(Null), new Handler(NullHandler));
     268      // TODO: make this configurable
     269      primitiveSerializers = new Dictionary<Type, IPrimitiveSerializer>();
     270      primitiveSerializers.Add(typeof(int), new Int2XMLSerializer());
     271      primitiveSerializers.Add(typeof(string), new String2XMLSerializer());
     272      customSerializers = new List<ICustomSerializer>();
     273      customSerializers.Add(new ArraySerializer());
     274      customSerializers.Add(new EnumerableSerializer());     
     275    }
     276    public object DeSerialize(IEnumerable<IParseToken> tokens) {
     277      foreach (IParseToken token in tokens) {
     278        handlers[token.GetType()].Invoke(token);
     279      }
     280      return compositeStack.Pop().obj;
     281    }
     282    private void CompositeStartHandler(IParseToken token) {
     283      CompositeStart start = (CompositeStart)token;
     284      object instance = null;
     285      if (this.FindCustomSerializer(start.Type) != null) {
     286        instance = null;
     287        compositeStack.Push(new AccessibleObject(null, new Dictionary<string, DataMemberAccessor>()));
     288        id2obj.Add(start.Id, null);
     289        // TODO: add warning proxy
     290      } else {
     291        instance = Activator.CreateInstance(start.Type);
     292        Dictionary<string, DataMemberAccessor> accessorDict =
     293        StorableAttribute.GetAutostorableAccessors(instance);
     294        compositeStack.Push(new AccessibleObject(instance, accessorDict));
     295        id2obj.Add(start.Id, instance);
     296      }
     297    }
     298    private void CompositeEndHandler(IParseToken token) {
     299      CompositeEnd end = (CompositeEnd)token;
     300      AccessibleObject accessibleObject = compositeStack.Pop();
     301      ICustomSerializer customSerializer = this.FindCustomSerializer(end.Type);
     302      if (customSerializer != null) {
     303        this.SetValue(end.Name,
     304          customSerializer.DeSerialize(accessibleObject.customValues, end.Type));
     305      } else {
     306        this.SetValue(end.Name, accessibleObject.obj);
     307      }
     308    }
     309    private ICustomSerializer FindCustomSerializer(Type type) {
     310      foreach (ICustomSerializer serializer in customSerializers) {
     311        if (serializer.CanSerialize(type))
     312          return serializer;
     313      }
     314      return null;
     315    }
     316    private void PrimitiveHandler(IParseToken token) {
     317      Primitive primitive = (Primitive)token;
     318      object value = primitiveSerializers[primitive.Type].DeSerialize(primitive.SerializedValue);
     319      this.SetValue(primitive.Name, value);     
     320    }
     321    private void ReferenceHandler(IParseToken token) {
     322      Reference reference = (Reference)token;     
     323      this.SetValue(reference.Name, this.id2obj[reference.Id]);           
     324    }
     325    private void NullHandler(IParseToken token) {
     326      Null nil = (Null)token;
     327      this.SetValue(nil.Name, null);     
     328    }
     329    private void SetValue(string name, object value) {
     330       if (compositeStack.Count == 0) {
     331        compositeStack.Push(new AccessibleObject(value, new Dictionary<string,DataMemberAccessor>()));
     332      } else {
     333        compositeStack.Peek().SetValue(name, value);
     334      }     
     335    }
    211336  }
    212337
     
    271396
    272397  }
    273  
     398
     399  #region parsing tokens
     400  public interface IParseToken { }
     401  public class CompositeStart : IParseToken {
     402    public string Name;
     403    public Type Type;   
     404    public int Id;
     405    public CompositeStart(string name, Type type, int id) {
     406      this.Name = name;
     407      this.Type = type;
     408      this.Id = id;     
     409    }
     410  }
     411  public class CompositeEnd : IParseToken {
     412    public string Name;
     413    public Type Type;   
     414    public int Id;
     415    public CompositeEnd(string name, Type type, int id) {
     416      this.Name = name;
     417      this.Type = type;
     418      this.Id = id;     
     419    }
     420  }
     421  public class Primitive : IParseToken {
     422    public string Name;
     423    public Type Type;
     424    public string SerializedValue;
     425    public Primitive(string name, Type type, string serilaizedValue) {
     426      this.Name = name;
     427      this.Type = type;
     428      this.SerializedValue = serilaizedValue;
     429    }
     430  }
     431  public class Reference : IParseToken {
     432    public string Name;
     433    public int Id;
     434    public Reference(string name, int id) {
     435      this.Name = name;
     436      this.Id = id;
     437    }
     438  }
     439  public class Null : IParseToken {
     440    public string Name;
     441    public Null(string name) {
     442      this.Name = name;
     443    }
     444  }
     445  #endregion
     446
     447
     448  public class XmlParser : IEnumerable<IParseToken> {
     449
     450    private XmlReader reader;
     451    private delegate IEnumerator<IParseToken> Handler();
     452    private Dictionary<string, Handler> handlers;
     453
     454    public XmlParser(StreamReader input) {
     455      XmlReaderSettings settings = new XmlReaderSettings();
     456      settings.ConformanceLevel = ConformanceLevel.Document;
     457      settings.IgnoreWhitespace = true;
     458      settings.IgnoreComments = true;
     459      this.reader = XmlReader.Create(input, settings);
     460      this.handlers = new Dictionary<string, Handler>();
     461      this.handlers.Add("PRIMITIVE", new Handler(ParsePrimitive));
     462      this.handlers.Add("COMPOSITE", new Handler(ParseComposite));
     463      this.handlers.Add("REFERENCE", new Handler(ParseReference));
     464      this.handlers.Add("NULL", new Handler(ParseNull));
     465    }
     466    public IEnumerator<IParseToken> GetEnumerator() {
     467      while (this.reader.Read()) {
     468        if (!reader.IsStartElement()) {         
     469          break;
     470        }
     471        IEnumerator<IParseToken> iterator;
     472        try {                     
     473            iterator = handlers[reader.Name].Invoke();         
     474        } catch (KeyNotFoundException) {         
     475          throw new InvalidOperationException(String.Format(
     476            "No handler for XML tag \"{0}\" installed",
     477            reader.Name));
     478        }
     479        while (iterator.MoveNext()) {
     480          yield return iterator.Current;
     481        }
     482      }     
     483    }
     484    private IEnumerator<IParseToken> ParsePrimitive() {
     485      yield return new Primitive(
     486        this.reader.GetAttribute("name"),
     487        Type.GetType(this.reader.GetAttribute("type")),
     488        this.reader.ReadString());     
     489    }
     490    private IEnumerator<IParseToken> ParseComposite() {
     491      string name = this.reader.GetAttribute("name");
     492      Type type = Type.GetType(this.reader.GetAttribute("type"));
     493      int id = int.Parse(this.reader.GetAttribute("id"));
     494      yield return new CompositeStart(name, type, id);       
     495      IEnumerator<IParseToken> iterator = this.GetEnumerator();
     496      while (iterator.MoveNext())
     497        yield return iterator.Current;
     498      yield return new CompositeEnd(name, type, id);     
     499    }
     500    private IEnumerator<IParseToken> ParseReference() {
     501      yield return new Reference(
     502        this.reader.GetAttribute("name"),
     503        int.Parse(this.reader.GetAttribute("ref")));     
     504    }
     505    private IEnumerator<IParseToken> ParseNull() {
     506      yield return new Null(this.reader.GetAttribute("name"));     
     507    }       
     508    IEnumerator IEnumerable.GetEnumerator() {
     509      return this.GetEnumerator();
     510    }   
     511  } 
    274512}
Note: See TracChangeset for help on using the changeset viewer.