Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Core/Serializer.cs @ 1703

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

Create folder with auxiliary classes. (#606)

File size: 5.4 KB
Line 
1using System.Collections.Generic;
2using System.Collections;
3using System;
4using System.Linq;
5using HeuristicLab.Persistence.Auxiliary;
6using HeuristicLab.Persistence.Interfaces;
7using HeuristicLab.Persistence.Core.Tokens;
8using HeuristicLab.Persistence.Default.Decomposers.Storable;
9using System.Text;
10using System.Runtime.InteropServices;
11
12namespace HeuristicLab.Persistence.Core {
13
14  public class Serializer : IEnumerable<ISerializationToken> {
15
16    class ReferenceEqualityComparer : IEqualityComparer<object> {
17
18      public bool Equals(object a, object b) {
19        return Object.ReferenceEquals(a, b);
20      }
21
22      public int GetHashCode(object obj) {
23        GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Weak);
24        int address = GCHandle.ToIntPtr(handle).ToInt32();
25        handle.Free();
26        return address;
27      }
28
29    }
30
31    private readonly object obj;
32    private readonly string rootName;
33    private readonly Dictionary<object, int> obj2id;
34    private readonly Dictionary<Type, int> typeCache;
35    private readonly Configuration configuration;
36
37    public List<TypeMapping> TypeCache {
38      get {
39        List<TypeMapping> result = new List<TypeMapping>();
40        foreach (var pair in typeCache) {
41          string serializer = null;
42          IFormatter f = configuration.GetFormatter(pair.Key);
43          if (f != null) {
44            serializer = f.GetType().VersionInvariantName();
45          } else {
46            IDecomposer d = configuration.GetDecomposer(pair.Key);
47            serializer = d.GetType().VersionInvariantName();
48          }
49          result.Add(new TypeMapping(pair.Value, pair.Key.VersionInvariantName(), serializer));
50        }
51        return result;
52      }
53    }
54
55    public Serializer(object obj, Configuration configuration) :
56      this(obj, configuration, "ROOT") { }
57
58    public Serializer(object obj, Configuration configuration, string rootName) {
59      this.obj = obj;
60      this.rootName = rootName;
61      this.configuration = configuration;
62      obj2id = new Dictionary<object, int>(new ReferenceEqualityComparer()) { { new object(), 0 } };
63      typeCache = new Dictionary<Type, int>();
64    }
65
66    IEnumerator IEnumerable.GetEnumerator() {
67      return GetEnumerator();
68    }
69
70    public IEnumerator<ISerializationToken> GetEnumerator() {
71      return Serialize(new DataMemberAccessor(rootName, null, () => obj, null));
72    }
73
74    private IEnumerator<ISerializationToken> Serialize(DataMemberAccessor accessor) {
75      object value = accessor.Get();
76      if (value == null)
77        return NullReferenceEnumerator(accessor.Name);
78      Type type = value.GetType();
79      if (obj2id.ContainsKey(value))
80        return ReferenceEnumerator(accessor.Name, obj2id[value]);
81      if (!typeCache.ContainsKey(type))
82        typeCache.Add(type, typeCache.Count);
83      int typeId = typeCache[type];
84      int? id = null;
85      if (!type.IsValueType) {
86        id = obj2id.Count;
87        obj2id.Add(value, (int)id);
88      }
89      IFormatter formatter = configuration.GetFormatter(type);
90      if (formatter != null)
91        return PrimitiveEnumerator(accessor.Name, typeId, formatter.Format(value), id);
92      IDecomposer decomposer = configuration.GetDecomposer(type);
93      if (decomposer != null)
94        return CompositeEnumerator(accessor.Name, decomposer.Decompose(value), id, typeId, decomposer.CreateMetaInfo(value));
95      throw new PersistenceException(
96          String.Format(
97          "No suitable method for serializing values of type \"{0}\" found\r\n" +
98          "Formatters:\r\n{1}\r\n" +
99          "Decomposers:\r\n{2}",
100          value.GetType().VersionInvariantName(),
101          string.Join("\r\n", configuration.Formatters.Select(f => f.GetType().VersionInvariantName()).ToArray()),
102          string.Join("\r\n", configuration.Decomposers.Select(d => d.GetType().VersionInvariantName()).ToArray())
103          ));
104
105    }
106
107    private IEnumerator<ISerializationToken> NullReferenceEnumerator(string name) {
108      yield return new NullReferenceToken(name);
109    }
110
111    private IEnumerator<ISerializationToken> ReferenceEnumerator(string name, int id) {
112      yield return new ReferenceToken(name, id);
113    }
114
115    private IEnumerator<ISerializationToken> PrimitiveEnumerator(string name,
116        int typeId, ISerialData serializedValue, int? id) {
117      yield return new PrimitiveToken(name, typeId, id, serializedValue);
118    }
119
120    private IEnumerator<ISerializationToken> CompositeEnumerator(
121        string name, IEnumerable<Tag> tags, int? id, int typeId, IEnumerable<Tag> metaInfo) {
122      yield return new BeginToken(name, typeId, id);
123      bool first = true;
124      foreach (var tag in metaInfo) {
125        IEnumerator<ISerializationToken> metaIt = Serialize(new DataMemberAccessor(tag.Value, tag.Name));
126        while (metaIt.MoveNext()) {
127          if (first) {
128            yield return new MetaInfoBeginToken();
129            first = false;
130          }
131          yield return metaIt.Current;
132        }
133      }
134      if (!first) {
135        yield return new MetaInfoEndToken();
136      }
137      foreach (var tag in tags) {
138        IEnumerator<ISerializationToken> it = Serialize(new DataMemberAccessor(tag.Value, tag.Name));
139        while (it.MoveNext())
140          yield return it.Current;
141      }
142      yield return new EndToken(name, typeId, id);
143    }
144
145  }
146
147
148}
Note: See TracBrowser for help on using the repository browser.