Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceReintegration/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs @ 15857

Last change on this file since 15857 was 15857, checked in by jkarder, 6 years ago

#2520: worked on conversions

File size: 41.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
25using System.Drawing;
26using System.Drawing.Imaging;
27using System.Globalization;
28using System.IO;
29using System.Linq;
30using System.Reflection;
31using Google.Protobuf;
32
33namespace HeuristicLab.Persistence {
34  [StorableType("8c7e99f5-092f-4cef-8b72-8afec1d10236")]
35  public abstract class BoxTransformer<T> : Transformer {
36    public override bool CanTransformType(Type type) {
37      return type == typeof(T);
38    }
39
40    public override Box ToBox(object o, Mapper mapper) {
41      var box = new Box {
42        TransformerId = mapper.GetTransformerId(this),
43        TypeBoxId = mapper.GetBoxId(o.GetType())
44      };
45      Populate(box, (T)o, mapper);
46      return box;
47    }
48
49    public override object ToObject(Box box, Mapper mapper) {
50      return Extract(box, (Type)mapper.GetObject(box.TypeBoxId), mapper);
51    }
52
53    protected abstract void Populate(Box box, T value, Mapper mapper);
54    protected abstract T Extract(Box box, Type type, Mapper mapper);
55  }
56
57  [Transformer("854156DA-2A37-450F-92ED-355FBBD8D131", 50)]
58  [StorableType("D48991BB-1DDA-4D64-A2E6-5B5608F85F2A")]
59  internal sealed class TypeTransformer : Transformer {
60    public override bool CanTransformType(Type type) {
61      return typeof(Type).IsAssignableFrom(type);
62    }
63
64    public override Box ToBox(object o, Mapper mapper) {
65      var box = new Box { TransformerId = mapper.GetTransformerId(this) };
66      Populate(box, o, mapper);
67      return box;
68    }
69
70    private void Populate(Box box, object value, Mapper mapper) {
71      var type = (Type)value;
72
73      if (type.IsGenericType) {
74        box.TypeId = mapper.GetTypeId(type.GetGenericTypeDefinition());
75        box.GenericTypeBoxIds.AddRange(type.GetGenericArguments().Select(mapper.GetBoxId));
76      } else if (type.IsArray) {
77        box.TypeId = mapper.GetTypeId(typeof(Array));
78        box.GenericTypeBoxIds.Add(mapper.GetBoxId(type.GetElementType()));
79      } else {
80        box.TypeId = mapper.GetTypeId(type);
81      }
82
83      if (StorableTypeAttribute.IsStorableType(type))
84        box.TypeVersion = StorableTypeAttribute.GetStorableTypeAttribute(type).Version;
85    }
86
87    public override object ToObject(Box box, Mapper mapper) {
88      return Extract(box, mapper.GetType(box.TypeId), mapper);
89    }
90
91    private object Extract(Box box, Type type, Mapper mapper) {
92      if (type.IsGenericType) {
93        return type.MakeGenericType(box.GenericTypeBoxIds.Select(x => (Type)mapper.GetObject(x)).ToArray());
94      } else if (type == typeof(Array)) {
95        return ((Type)mapper.GetObject(box.GenericTypeBoxIds[0])).MakeArrayType();
96      } else {
97        return type;
98      }
99    }
100  }
101
102  [Transformer("4C610596-5234-4C49-998E-30007D64492E", 100)]
103  [StorableType("69870239-00B7-4C9D-AF0B-14208069FAC8")]
104  internal sealed class StringBoxTransformer : BoxTransformer<string> {
105    protected override void Populate(Box box, string value, Mapper mapper) { box.UInt = mapper.GetStringId(value); }
106    protected override string Extract(Box box, Type type, Mapper mapper) { return mapper.GetString(box.UInt); }
107  }
108
109  [Transformer("58E69402-2533-426A-B9B5-9F2EB5241560", 101)]
110  [StorableType("667182BB-D2D5-46C6-97CB-593CE1B19CBC")]
111  internal sealed class BoolBoxTransformer : BoxTransformer<bool> {
112    protected override void Populate(Box box, bool value, Mapper mapper) { box.Bool = value; }
113    protected override bool Extract(Box box, Type type, Mapper mapper) { return box.Bool; }
114  }
115
116  [Transformer("D78F3391-3CAE-4376-9348-7FB38A4DE0EB", 102)]
117  [StorableType("1E75D1D8-3FAD-4D68-86BB-95DE981FDDD2")]
118  internal sealed class IntBoxTransformer : BoxTransformer<int> {
119    protected override void Populate(Box box, int value, Mapper mapper) { box.Int = value; }
120    protected override int Extract(Box box, Type type, Mapper mapper) { return box.Int; }
121  }
122
123  [Transformer("25881263-F452-492E-9FD1-24E1938B048B", 103)]
124  [StorableType("7742A4A3-31B4-4449-9657-0D9F50F2382F")]
125  internal sealed class UIntBoxTransformer : BoxTransformer<uint> {
126    protected override void Populate(Box box, uint value, Mapper mapper) { box.UInt = value; }
127    protected override uint Extract(Box box, Type type, Mapper mapper) { return box.UInt; }
128  }
129
130  [Transformer("F4175165-382B-4B03-921E-5F923510FB1E", 104)]
131  [StorableType("985427E0-E4F0-4182-8D30-63DA7FB69735")]
132  internal sealed class LongBoxTransformer : BoxTransformer<long> {
133    protected override void Populate(Box box, long value, Mapper mapper) { box.Long = value; }
134    protected override long Extract(Box box, Type type, Mapper mapper) { return box.Long; }
135  }
136
137  [Transformer("E8F63973-3C0C-4FA9-B068-40EF4463B30B", 105)]
138  [StorableType("C9F95D84-BCDC-498E-A9AE-7187E483BBBA")]
139  internal sealed class ULongBoxTransformer : BoxTransformer<ulong> {
140    protected override void Populate(Box box, ulong value, Mapper mapper) { box.ULong = value; }
141    protected override ulong Extract(Box box, Type type, Mapper mapper) { return box.ULong; }
142  }
143
144  [Transformer("15489146-EA11-4B90-8020-AF5C10A2531C", 106)]
145  [StorableType("AF1C5176-859C-423B-A2BF-2AEA4D0792C7")]
146  internal sealed class FloatBoxTransformer : BoxTransformer<float> {
147    protected override void Populate(Box box, float value, Mapper mapper) { box.Float = value; }
148    protected override float Extract(Box box, Type type, Mapper mapper) { return box.Float; }
149  }
150
151  [Transformer("91FD51F3-9C47-4944-AC85-273ED0561E87", 107)]
152  [StorableType("4AB25AE9-2600-4041-8F31-C02CCE9A3BEC")]
153  internal sealed class DoubleBoxTransformer : BoxTransformer<double> {
154    protected override void Populate(Box box, double value, Mapper mapper) { box.Double = value; }
155    protected override double Extract(Box box, Type type, Mapper mapper) { return box.Double; }
156  }
157
158  [Transformer("BCB087EA-E477-47EB-9BCE-8C64BAC2F288", 108)]
159  [StorableType("341C2F99-8849-408E-99AA-7700FE0FB789")]
160  internal sealed class ByteBoxTransformer : BoxTransformer<byte> {
161    protected override void Populate(Box box, byte value, Mapper mapper) { box.UInt = value; }
162    protected override byte Extract(Box box, Type type, Mapper mapper) { return (byte)box.UInt; }
163  }
164
165  [Transformer("B90F61D9-75D0-4CAC-AF93-B8C6AB68F642", 109)]
166  [StorableType("FEC52DD5-A422-45C4-995F-09F3B0DEC13F")]
167  internal sealed class SByteBoxTransformer : BoxTransformer<sbyte> {
168    protected override void Populate(Box box, sbyte value, Mapper mapper) { box.Int = value; }
169    protected override sbyte Extract(Box box, Type type, Mapper mapper) { return (sbyte)box.Int; }
170  }
171
172  [Transformer("95EB44A4-EADD-4DA9-B60F-3262FAD6134B", 110)]
173  [StorableType("48744968-15F2-4B22-AAF2-6C0910239384")]
174  internal sealed class ShortBoxTransformer : BoxTransformer<short> {
175    protected override void Populate(Box box, short value, Mapper mapper) { box.Int = value; }
176    protected override short Extract(Box box, Type type, Mapper mapper) { return (short)box.Int; }
177  }
178
179  [Transformer("E3A33614-9120-400E-BAD9-2594F6804DA8", 111)]
180  [StorableType("DCF05BA3-3C57-4DBB-96B4-B2CE31CA60C5")]
181  internal sealed class UShortBoxTransformer : BoxTransformer<ushort> {
182    protected override void Populate(Box box, ushort value, Mapper mapper) { box.Int = value; }
183    protected override ushort Extract(Box box, Type type, Mapper mapper) { return (ushort)box.Int; }
184  }
185
186  [Transformer("C64EA534-E2E1-48F0-86C5-648AA02117BC", 112)]
187  [StorableType("142980B3-A251-48D2-BF02-A66C483D6385")]
188  internal sealed class CharBoxTransformer : BoxTransformer<char> {
189    protected override void Populate(Box box, char value, Mapper mapper) { box.UInt = value; }
190    protected override char Extract(Box box, Type type, Mapper mapper) { return (char)box.UInt; }
191  }
192
193  [Transformer("D50C4782-7211-4476-B50F-7D3378EE3E53", 200)]
194  [StorableType("4397B775-7D48-4C2A-8D28-ACC8C196CF70")]
195  internal sealed class StringArrayBoxTransformer : BoxTransformer<string[]> {
196    protected override void Populate(Box box, string[] value, Mapper mapper) { box.UInts.AddRange(value.Select(mapper.GetStringId)); }
197    protected override string[] Extract(Box box, Type type, Mapper mapper) { return box.UInts.Select(mapper.GetString).ToArray(); }
198  }
199
200  [Transformer("C9CFA67B-DF13-4125-B781-98EC8F5E390F", 201)]
201  [StorableType("9719DB59-C6BC-4788-BBB0-389A1B49CFEE")]
202  internal sealed class BoolArrayBoxTransformer : BoxTransformer<bool[]> {
203    protected override void Populate(Box box, bool[] value, Mapper mapper) { box.Bools.AddRange(value); }
204    protected override bool[] Extract(Box box, Type type, Mapper mapper) { return box.Bools.ToArray(); }
205  }
206
207  [Transformer("BA2E18F6-5C17-40CA-A5B8-5690C5EFE872", 202)]
208  [StorableType("6548E9F0-621D-47BA-A605-8A47EF85C231")]
209  internal sealed class IntArrayBoxTransformer : BoxTransformer<int[]> {
210    protected override void Populate(Box box, int[] value, Mapper mapper) { box.Ints.AddRange(value); }
211    protected override int[] Extract(Box box, Type type, Mapper mapper) { return box.Ints.ToArray(); }
212  }
213
214  [Transformer("EEE7710D-86DE-47E1-887D-BDA2996B141E", 203)]
215  [StorableType("4127B466-AFC0-4050-8C45-1376A0E3E016")]
216  internal sealed class UnsignedIntArrayBoxTransformer : BoxTransformer<uint[]> {
217    protected override void Populate(Box box, uint[] value, Mapper mapper) { box.UInts.AddRange(value); }
218    protected override uint[] Extract(Box box, Type type, Mapper mapper) { return box.UInts.ToArray(); }
219  }
220
221  [Transformer("557932AA-F023-477F-AAD0-5098E8B8CD56", 204)]
222  [StorableType("C2ED50C8-C340-40C1-B00C-2F398EB709A0")]
223  internal sealed class LongArrayBoxTransformer : BoxTransformer<long[]> {
224    protected override void Populate(Box box, long[] value, Mapper mapper) { box.Longs.AddRange(value); }
225    protected override long[] Extract(Box box, Type type, Mapper mapper) { return box.Longs.ToArray(); }
226  }
227
228  [Transformer("CFF20DEE-2A55-4D04-B543-A4C7E0A8F7BF", 205)]
229  [StorableType("641AE353-5373-4811-BACB-C13D3144809C")]
230  internal sealed class UnsignedLongArrayBoxTransformer : BoxTransformer<ulong[]> {
231    protected override void Populate(Box box, ulong[] value, Mapper mapper) { box.ULongs.AddRange(value); }
232    protected override ulong[] Extract(Box box, Type type, Mapper mapper) { return box.ULongs.ToArray(); }
233  }
234
235  [Transformer("2A0F766D-FE71-4415-A75F-A32FB8BB9E2D", 206)]
236  [StorableType("AEE9384F-3857-4CE4-AE30-B99474F7A6C9")]
237  internal sealed class FloatArrayBoxTransformer : BoxTransformer<float[]> {
238    protected override void Populate(Box box, float[] value, Mapper mapper) { box.Floats.AddRange(value); }
239    protected override float[] Extract(Box box, Type type, Mapper mapper) { return box.Floats.ToArray(); }
240  }
241
242  [Transformer("192A8F7D-84C7-44BF-B0CA-AD387A241AAD", 207)]
243  [StorableType("17D0BA74-CB84-405C-8DBB-D9E361274A0A")]
244  internal sealed class DoubleArrayBoxTransformer : BoxTransformer<double[]> {
245    protected override void Populate(Box box, double[] value, Mapper mapper) { box.Doubles.AddRange(value); }
246    protected override double[] Extract(Box box, Type type, Mapper mapper) { return box.Doubles.ToArray(); }
247  }
248
249  [Transformer("3A35CECE-9953-4C29-A796-A56C02D80A05", 208)]
250  [StorableType("A076D11E-89AA-43C8-87F5-A0D0F52569EB")]
251  internal sealed class ByteArrayBoxTransformer : BoxTransformer<byte[]> {
252    protected override void Populate(Box box, byte[] value, Mapper mapper) { box.Bytes = ByteString.CopyFrom(value); }
253    protected override byte[] Extract(Box box, Type type, Mapper mapper) { return box.Bytes.ToArray(); }
254  }
255
256  [Transformer("880D4A63-6C77-4F9F-8F7C-2D365F0AE829", 209)]
257  [StorableType("74F6FD4B-D7D7-43CD-B28B-3A775505FEE3")]
258  internal sealed class SByteArrayBoxTransformer : BoxTransformer<sbyte[]> {
259    protected override void Populate(Box box, sbyte[] value, Mapper mapper) { box.Bytes = ByteString.CopyFrom(value.Select(x => (byte)x).ToArray()); }
260    protected override sbyte[] Extract(Box box, Type type, Mapper mapper) { return box.Bytes.Select(x => (sbyte)x).ToArray(); }
261  }
262
263  [Transformer("9786E711-7C1D-4761-BD6B-445793834264", 210)]
264  [StorableType("5F32480E-AACB-4DB3-ADE3-1CF36E33C037")]
265  internal sealed class ShortArrayBoxTransformer : BoxTransformer<short[]> {
266    protected override void Populate(Box box, short[] value, Mapper mapper) {
267      var res = new byte[value.Length * 2];
268      for (int i = 0; i < value.Length; i++) {
269        var bytes = BitConverter.GetBytes(value[i]);
270        Array.Copy(bytes, 0, res, i * 2, 2);
271      }
272      box.Bytes = ByteString.CopyFrom(res);
273    }
274
275    protected override short[] Extract(Box box, Type type, Mapper mapper) {
276      var bytes = box.Bytes.ToArray();
277      var res = new short[bytes.Length / 2];
278      for (int i = 0; i < bytes.Length; i += 2) {
279        res[i / 2] = BitConverter.ToInt16(bytes, i);
280      }
281      return res;
282    }
283  }
284
285  [Transformer("1AAC2625-356C-40BC-8CB4-15CB3D047EB8", 211)]
286  [StorableType("C303B4CF-FFD0-47E2-9D94-07F2D558D17F")]
287  internal sealed class UShortArrayTransformer : BoxTransformer<ushort[]> {
288    protected override void Populate(Box box, ushort[] value, Mapper mapper) {
289      var res = new byte[value.Length * 2];
290      for (int i = 0; i < value.Length; i++) {
291        var bytes = BitConverter.GetBytes(value[i]);
292        Array.Copy(bytes, 0, res, i * 2, 2);
293      }
294      box.Bytes = ByteString.CopyFrom(res);
295    }
296
297    protected override ushort[] Extract(Box box, Type type, Mapper mapper) {
298      var bytes = box.Bytes.ToArray();
299      var res = new ushort[bytes.Length / 2];
300      for (int i = 0; i < bytes.Length; i += 2) {
301        res[i / 2] = BitConverter.ToUInt16(bytes, i);
302      }
303      return res;
304    }
305  }
306
307  [Transformer("12F19098-5D49-4C23-8897-69087F1C146D", 212)]
308  [StorableType("55F7C8B0-F2AA-4830-857D-6CE2807DA138")]
309  internal sealed class CharArrayTransformer : BoxTransformer<char[]> {
310    protected override void Populate(Box box, char[] value, Mapper mapper) {
311      var res = new byte[value.Length * 2];
312      for (int i = 0; i < value.Length; i++) {
313        var bytes = BitConverter.GetBytes(value[i]);
314        Array.Copy(bytes, 0, res, i * 2, 2);
315      }
316      box.Bytes = ByteString.CopyFrom(res);
317    }
318    protected override char[] Extract(Box box, Type type, Mapper mapper) {
319      var bytes = box.Bytes.ToArray();
320      var res = new char[bytes.Length / 2];
321      for (int i = 0; i < bytes.Length; i += 2) {
322        res[i / 2] = BitConverter.ToChar(bytes, i);
323      }
324      return res;
325    }
326  }
327
328  [Transformer("05AE4C5D-4D0C-47C7-B6D5-F04230C6F565", 301)]
329  [StorableType("A74820C8-F400-462A-913A-610BB588D04A")]
330  internal sealed class ArrayBoxTransformer : BoxTransformer<object> {
331    public override bool CanTransformType(Type type) {
332      return type.IsArray;
333    }
334
335    protected override void Populate(Box box, object value, Mapper mapper) {
336      var type = value.GetType();
337      var array = (Array)value;
338      var rank = array.Rank;
339
340      var uints = box.UInts;
341      uints.Add((uint)rank);
342
343      int[] lengths = new int[rank];
344      int[] lowerBounds = new int[rank];
345      for (int i = 0; i < rank; i++) {
346        uints.Add(mapper.GetBoxId(lengths[i] = array.GetLength(i)));
347        uints.Add(mapper.GetBoxId(lowerBounds[i] = array.GetLowerBound(i)));
348      }
349
350      int[] positions = (int[])lowerBounds.Clone();
351      while (positions[rank - 1] < lengths[rank - 1] + lowerBounds[rank - 1]) {
352        uints.Add(mapper.GetBoxId(array.GetValue(positions)));
353        positions[0] += 1;
354        for (int i = 0; i < rank - 1; i++) {
355          if (positions[i] >= lowerBounds[i] + lengths[i]) {
356            positions[i] = lowerBounds[i];
357            positions[i + 1] += 1;
358          } else {
359            break;
360          }
361        }
362      }
363    }
364
365    protected override object Extract(Box box, Type type, Mapper mapper) {
366      var uints = box.UInts;
367      var rank = (int)uints[0];
368
369      int[] lengths = new int[rank], lowerBounds = new int[rank];
370      for (int i = 0; i < rank; i++) {
371        lengths[i] = (int)mapper.GetObject(uints[2 * i + 1]);
372        lowerBounds[i] = (int)mapper.GetObject(uints[2 * i + 2]);
373      }
374
375      return Array.CreateInstance(type.GetElementType(), lengths, lowerBounds);
376    }
377
378    public override void FillFromBox(object obj, Box box, Mapper mapper) {
379      var array = (Array)obj;
380      var uints = box.UInts;
381      var rank = (int)uints[0];
382
383      int[] lengths = new int[rank], lowerBounds = new int[rank];
384      for (int i = 0; i < rank; i++) {
385        lengths[i] = (int)mapper.GetObject(uints[2 * i + 1]);
386        lowerBounds[i] = (int)mapper.GetObject(uints[2 * i + 2]);
387      }
388
389      int[] positions = (int[])lowerBounds.Clone();
390      var e = uints.Skip(1 + 2 * rank).GetEnumerator();
391      while (e.MoveNext()) {
392        int[] currentPositions = positions;
393        array.SetValue(mapper.GetObject(e.Current), currentPositions);
394        positions[0] += 1;
395        for (int i = 0; i < rank - 1; i++) {
396          if (positions[i] >= lengths[i] + lowerBounds[i]) {
397            positions[i] = lowerBounds[i];
398            positions[i + 1] += 1;
399          } else {
400            break;
401          }
402        }
403      }
404    }
405  }
406
407  [Transformer("26AD5F85-1D77-4579-BCB9-CD409B48AC7A", 302)]
408  [StorableType("A96E2C1E-EBDF-4D81-A0ED-91677BC84FEE")]
409  internal sealed class EnumerableBoxTransformer : BoxTransformer<object> {
410    private static readonly HashSet<Type> supportedTypes = new HashSet<Type> {
411      typeof(Stack<>), typeof(Stack),
412      typeof(Queue<>), typeof(Queue),
413      typeof(HashSet<>),
414      typeof(List<>), typeof(ArrayList)
415    };
416
417    public override bool CanTransformType(Type type) {
418      return type.IsGenericType && supportedTypes.Contains(type.GetGenericTypeDefinition()) || supportedTypes.Contains(type);
419    }
420
421    protected override void Populate(Box box, object value, Mapper mapper) {
422      var uints = box.UInts;
423
424      var type = value.GetType();
425      var propertyInfo = type.GetProperty("Comparer");
426      if (propertyInfo != null) {
427        var comparer = propertyInfo.GetValue(value);
428        var comparerType = comparer.GetType();
429        if (StorableTypeAttribute.IsStorableType(comparerType))
430          box.ComparerId = mapper.GetBoxId(comparer);
431        else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
432          throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
433        else
434          box.ComparerId = mapper.GetBoxId(comparerType);
435      }
436
437      foreach (var item in (IEnumerable)value)
438        uints.Add(mapper.GetBoxId(item));
439    }
440
441    protected override object Extract(Box box, Type type, Mapper mapper) {
442      return Activator.CreateInstance(type);
443    }
444
445    public override void FillFromBox(object obj, Box box, Mapper mapper) {
446      var uints = box.UInts;
447      var elements = uints.Select(mapper.GetObject);
448      var type = obj.GetType();
449
450      string methodName = string.Empty;
451      if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Stack<>) || type == typeof(Stack)) {
452        elements = elements.Reverse();
453        methodName = "Push";
454      } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Queue<>) || type == typeof(Queue)) {
455        methodName = "Enqueue";
456      } else {
457        methodName = "Add";
458        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>)) {
459          var fieldInfo = type.GetField("m_comparer", BindingFlags.NonPublic | BindingFlags.Instance);
460          var comparerObj = mapper.GetObject(box.ComparerId);
461          var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
462          fieldInfo.SetValue(obj, comparer);
463        }
464      }
465
466      MethodInfo addMethod = type.GetMethod(methodName);
467      foreach (var e in elements)
468        addMethod.Invoke(obj, new[] { e });
469    }
470  }
471
472  [Transformer("C47A62F5-F113-4A43-A8EE-CF817EC799A2", 303)]
473  [StorableType("BA53DF84-DC97-4D8D-A493-868972ED1002")]
474  internal sealed class DictionaryTransformer : BoxTransformer<object> {
475    public override bool CanTransformType(Type type) {
476      return type.IsGenericType && typeof(Dictionary<,>) == type.GetGenericTypeDefinition();
477    }
478
479    protected override void Populate(Box box, object value, Mapper mapper) {
480      var kvps = box.KeyValuePairs;
481      foreach (DictionaryEntry item in (IDictionary)value)
482        kvps.Add(mapper.GetBoxId(item.Key), mapper.GetBoxId(item.Value));
483
484      var type = value.GetType();
485      var propertyInfo = type.GetProperty("Comparer");
486      var comparer = propertyInfo.GetValue(value);
487
488      var comparerType = comparer.GetType();
489      if (StorableTypeAttribute.IsStorableType(comparerType))
490        box.ComparerId = mapper.GetBoxId(comparer);
491      else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
492        throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
493      else
494        box.ComparerId = mapper.GetBoxId(comparerType);
495    }
496
497    protected override object Extract(Box box, Type type, Mapper mapper) {
498      return Activator.CreateInstance(type, box.KeyValuePairs.Count);
499    }
500
501    public override void FillFromBox(object obj, Box box, Mapper mapper) {
502      var type = obj.GetType();
503      var comparerObj = mapper.GetObject(box.ComparerId);
504      var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
505
506      var fieldInfo = type.GetField("comparer", BindingFlags.NonPublic | BindingFlags.Instance);
507      fieldInfo.SetValue(obj, comparer);
508
509      var addMethod = type.GetMethod("Add");
510      var kvps = box.KeyValuePairs;
511      foreach (var entry in kvps) {
512        var key = mapper.GetObject(entry.Key);
513        var value = mapper.GetObject(entry.Value);
514        addMethod.Invoke(obj, new[] { key, value });
515      }
516    }
517
518    [Transformer("93FF076B-BC4B-4C39-8C40-15E004468C98", 219)]
519    [StorableType("F8A7DBB4-E1CE-4DB8-905E-F3A05F5CA000")]
520    internal sealed class EnumTransformer : Transformer {
521      public override bool CanTransformType(Type type) {
522        return typeof(Enum).IsAssignableFrom(type);
523      }
524
525      public override Box ToBox(object o, Mapper mapper) {
526        var box = new Box {
527          TransformerId = mapper.GetTransformerId(this),
528          TypeId = mapper.GetStringId(o.GetType().AssemblyQualifiedName),
529          UInt = mapper.GetStringId(Enum.Format(o.GetType(), o, "G")),
530        };
531        return box;
532      }
533
534      public override object ToObject(Box box, Mapper mapper) {
535        return Enum.Parse(Type.GetType(mapper.GetString(box.TypeId)), mapper.GetString(box.UInt));
536      }
537    }
538
539    [Transformer("268617FE-3F0F-4029-8248-EDA420901FB6", 10000)]
540    [StorableType("320CBA58-1AAF-492B-BE3B-F59EEA085EBE")]
541    internal sealed class ObjectBoxTransformer : BoxTransformer<object> {
542      protected override void Populate(Box box, object value, Mapper mapper) { }
543      protected override object Extract(Box box, Type type, Mapper mapper) { return new object(); }
544    }
545  }
546
547  [Transformer("90F9F16D-9F94-491B-AC3B-E1C6F3432127", 400)]
548  [StorableType("C3C23FEE-DB96-4CEA-A38B-6BB73811F877")]
549  internal sealed class DecimalBoxTransformer : BoxTransformer<decimal> {
550    protected override decimal Extract(Box box, Type type, Mapper mapper) {
551      return ParseG30(mapper.GetString(box.UInt));
552    }
553
554    protected override void Populate(Box box, decimal value, Mapper mapper) {
555      box.UInt = mapper.GetStringId(FormatG30(value));
556    }
557
558    private static decimal ParseG30(string s) {
559      decimal d;
560      if (decimal.TryParse(s,
561        NumberStyles.AllowDecimalPoint |
562        NumberStyles.AllowExponent |
563        NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out d))
564        return d;
565      throw new FormatException(
566        string.Format("Invalid decimal G30 number format \"{0}\" could not be parsed", s));
567    }
568
569    private static string FormatG30(decimal d) {
570      return d.ToString("g30", CultureInfo.InvariantCulture);
571    }
572  }
573
574  [Transformer("1C6C350F-B2C8-40F0-A964-54DDB0D087A3", 401)]
575  [StorableType("9D99D155-E3BB-40CE-AF64-6E153D876148")]
576  internal sealed class DateTimeBoxTransformer : BoxTransformer<DateTime> {
577    protected override void Populate(Box box, DateTime value, Mapper mapper) { box.Long = value.Ticks; }
578    protected override DateTime Extract(Box box, Type type, Mapper mapper) { return new DateTime(box.Long); }
579  }
580
581  [Transformer("964074C9-4B82-4725-97AF-612A193EA5C6", 402)]
582  [StorableType("9CA7C1F7-784C-48D5-A6F4-E1FD7B3A2FEC")]
583  internal sealed class TimeSpanBoxTransformer : BoxTransformer<TimeSpan> {
584    protected override void Populate(Box box, TimeSpan value, Mapper mapper) { box.Long = value.Ticks; }
585    protected override TimeSpan Extract(Box box, Type type, Mapper mapper) { return new TimeSpan(box.Long); }
586  }
587
588  [Transformer("B0C0165B-6279-4CC3-8DB7-D36898BFBC38", 403)]
589  [StorableType("ED6B7AE1-CE2B-4891-9BF3-72F5D1D67D93")]
590  internal sealed class PointTransformer : BoxTransformer<Point> {
591    protected override void Populate(Box box, Point value, Mapper mapper) {
592      box.Ints.AddRange(new[] { value.X, value.Y });
593    }
594
595    protected override Point Extract(Box box, Type type, Mapper mapper) {
596      var ints = box.Ints;
597      return new Point(ints[0], ints[1]);
598    }
599  }
600
601  [Transformer("D0ADB806-2DFD-459D-B5DA-14B5F1152534", 404)]
602  [StorableType("B13D6153-E71D-4B76-9893-81D3570403E8")]
603  internal sealed class BitmapTransformer : BoxTransformer<Bitmap> {
604    protected override void Populate(Box box, Bitmap value, Mapper mapper) {
605      lock (value)
606        using (var ms = new MemoryStream()) {
607          value.Save(ms, ImageFormat.Png);
608          box.Bytes = ByteString.CopyFrom(ms.ToArray());
609        }
610    }
611
612    protected override Bitmap Extract(Box box, Type type, Mapper mapper) {
613      using (var ms = new MemoryStream()) {
614        ms.Write(box.Bytes.ToArray(), 0, box.Bytes.Length);
615        ms.Seek(0, SeekOrigin.Begin);
616        return new Bitmap(ms);
617      }
618    }
619  }
620
621  [Transformer("AFF27987-3301-4D70-9601-EFCA31BDA0DB", 405)]
622  [StorableType("B9F9A371-4DCB-478B-B0D4-6F87A15C02B5")]
623  internal sealed class FontTransformer : BoxTransformer<Font> {
624    protected override void Populate(Box box, Font value, Mapper mapper) {
625      var uints = box.UInts;
626      uints.Add(mapper.GetStringId(GetFontFamilyName(value.FontFamily)));
627      uints.Add(mapper.GetBoxId(value.Size));
628      uints.Add(mapper.GetBoxId(value.Style));
629      uints.Add(mapper.GetBoxId(value.Unit));
630      uints.Add(mapper.GetBoxId(value.GdiCharSet));
631      uints.Add(mapper.GetBoxId(value.GdiVerticalFont));
632    }
633
634    protected override Font Extract(Box box, Type type, Mapper mapper) {
635      var fontData = box.UInts;
636      return new Font(
637        GetFontFamily(mapper.GetString(fontData[0])),
638        (float)mapper.GetObject(fontData[1]),
639        (FontStyle)mapper.GetObject(fontData[2]),
640        (GraphicsUnit)mapper.GetObject(fontData[3]),
641        (byte)mapper.GetObject(fontData[4]),
642        (bool)mapper.GetObject(fontData[5])
643      );
644    }
645
646    public const string GENERIC_MONOSPACE_NAME = "_GenericMonospace";
647    public const string GENERIC_SANS_SERIF_NAME = "_GenericSansSerif";
648    public const string GENERIC_SERIF_NAME = "_GenericSerif";
649
650    public static FontFamily GetFontFamily(string name) {
651      if (name == GENERIC_MONOSPACE_NAME) return FontFamily.GenericMonospace;
652      if (name == GENERIC_SANS_SERIF_NAME) return FontFamily.GenericSansSerif;
653      if (name == GENERIC_SERIF_NAME) return FontFamily.GenericSerif;
654      return new FontFamily(name);
655    }
656
657    public static string GetFontFamilyName(FontFamily ff) {
658      if (ff.Equals(FontFamily.GenericMonospace)) return GENERIC_MONOSPACE_NAME;
659      if (ff.Equals(FontFamily.GenericSansSerif)) return GENERIC_SANS_SERIF_NAME;
660      if (ff.Equals(FontFamily.GenericSerif)) return GENERIC_SERIF_NAME;
661      return ff.Name;
662    }
663  }
664
665  [Transformer("D912D573-CE41-40B8-8F95-646C183662F6", 406)]
666  [StorableType("3ED2C12F-BE41-45F5-AA0A-C2F23EB99FBD")]
667  internal sealed class KeyValuePairBoxTransformer : BoxTransformer<object> {
668    public override bool CanTransformType(Type type) {
669      return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
670    }
671
672    protected override void Populate(Box box, object value, Mapper mapper) {
673      var uints = box.UInts;
674
675      var type = value.GetType();
676      var pair = new[] {
677        mapper.GetBoxId(type.GetProperty("Key").GetValue(value)) ,
678        mapper.GetBoxId(type.GetProperty("Value").GetValue(value))
679      };
680
681      uints.AddRange(pair);
682    }
683
684    public override void FillFromBox(object obj, Box box, Mapper mapper) {
685      var uints = box.UInts;
686      var key = mapper.GetObject(uints[0]);
687      var val = mapper.GetObject(uints[1]);
688      var type = obj.GetType();
689      //DataMemberAccessor.GenerateFieldSetter(type.GetField("key", BindingFlags.NonPublic | BindingFlags.Instance))(obj, key);
690      //DataMemberAccessor.GenerateFieldSetter(type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance))(obj, val);
691      type.GetField("key", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(obj, key);
692      type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(obj, val);
693    }
694
695    protected override object Extract(Box box, Type type, Mapper mapper) {
696      return Activator.CreateInstance(type);
697    }
698  }
699
700  [Transformer("BBA08D33-FDA4-4EB6-8D94-9BF3D30C3E11", 407)]
701  [StorableType("B0333A12-7D91-47A5-ACD4-49E43E5A18DC")]
702  internal sealed class TupleBoxTransformer : BoxTransformer<object> {
703    private static readonly HashSet<Type> supportedTypes = new HashSet<Type> {
704      typeof(Tuple<>), typeof(Tuple<,>), typeof(Tuple<,,>), typeof(Tuple<,,,>),
705      typeof(Tuple<,,,,>), typeof(Tuple<,,,,,>), typeof(Tuple<,,,,,,>), typeof(Tuple<,,,,,,,>)
706    };
707
708    public override bool CanTransformType(Type type) {
709      return type.IsGenericType && supportedTypes.Contains(type.GetGenericTypeDefinition());
710    }
711
712    protected override void Populate(Box box, object value, Mapper mapper) {
713      var type = value.GetType();
714      var uints = box.UInts;
715      for (int i = 1; i <= type.GetGenericArguments().Length; i++) {
716        string name = string.Format("Item{0}", i);
717        uints.Add(mapper.GetBoxId(type.GetProperty(name).GetValue(value)));
718      }
719    }
720
721    protected override object Extract(Box box, Type type, Mapper mapper) {
722      var defaultValues = type.GetGenericArguments().Select(x =>
723        x.IsValueType ? Activator.CreateInstance(x) : null
724      ).ToArray();
725      return Activator.CreateInstance(type, defaultValues);
726    }
727
728    public override void FillFromBox(object obj, Box box, Mapper mapper) {
729      var uints = box.UInts;
730      var elements = uints.Select(mapper.GetObject).ToArray();
731      var type = obj.GetType();
732      for (int i = 1; i <= elements.Length; i++) {
733        string name = string.Format("m_Item{0}", i);
734        DataMemberAccessor.GenerateFieldSetter(type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance))(obj, elements[i - 1]);
735      }
736    }
737  }
738
739  [Transformer("731F9A18-6BF4-43BE-95CF-8205552C9B70", 500)]
740  [StorableType("73FCDE79-436D-476E-B2EA-A7A1A4A810B5")]
741  internal sealed class StructBoxTransformer : BoxTransformer<object> {
742    public override bool CanTransformType(Type type) {
743      return type.IsValueType && !type.IsPrimitive && !type.IsEnum && type.IsSealed;
744    }
745
746    protected override void Populate(Box box, object value, Mapper mapper) {
747      var type = value.GetType();
748
749      var kvps = box.KeyValuePairs;
750      foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
751        kvps.Add(mapper.GetStringId(fieldInfo.Name), mapper.GetBoxId(fieldInfo.GetValue(value)));
752    }
753
754    protected override object Extract(Box box, Type type, Mapper mapper) {
755      var obj = Activator.CreateInstance(type);
756
757      var kvps = box.KeyValuePairs;
758      foreach (var t in kvps) {
759        string name = mapper.GetString(t.Key);
760        MemberInfo[] mis = type.GetMember(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
761        if (mis.Length != 1)
762          throw new Exception("ambiguous struct member name " + name);
763        MemberInfo mi = mis[0];
764        if (StorableAttribute.IsStorable(mi))
765          throw new PersistenceException("Don't use stroable attributes for structs as all fields are serialized automatically.");
766        if (mi.MemberType == MemberTypes.Field)
767          ((FieldInfo)mi).SetValue(obj, mapper.GetObject(t.Value));
768        else
769          throw new Exception("invalid struct member type " + mi.MemberType.ToString());
770      }
771
772      return obj;
773    }
774  }
775
776  [Transformer("78556C88-0FEE-4602-95C7-A469B2DDB468", 600)]
777  [StorableType("3A578289-43CA-40F8-9F1E-2BDD255CB8FB")]
778  internal sealed class StorableTypeBoxTransformer : BoxTransformer<object> {
779    public override bool CanTransformType(Type type) {
780      return StorableTypeAttribute.IsStorableType(type) && !type.IsValueType && !type.IsEnum || // don't transform structs or enums
781        type.BaseType != null && CanTransformType(type.BaseType);
782    }
783
784    protected override void Populate(Box box, object value, Mapper mapper) {
785      var kvps = box.KeyValuePairs;
786      var parentTypeVersions = box.UInts;
787      var emptyArgs = new object[0];
788
789      var originalType = value.GetType();
790
791      // traverse type hierarchy
792      var type = originalType;
793      while (StorableTypeAttribute.IsStorableType(type)) {
794        var typeInfo = Mapper.StaticCache.GetTypeInfo(type);
795        var attribute = typeInfo.StorableTypeAttribute;
796        var guid = typeInfo.StorableTypeAttribute.Guid;
797
798        foreach (var hook in typeInfo.BeforeSerializationHooks)
799          hook.Invoke(value, emptyArgs);
800
801        foreach (var componentInfo in typeInfo.Fields) {
802          var field = (FieldInfo)componentInfo.MemberInfo;
803          kvps.Add(
804            mapper.GetStringId(componentInfo.FullName),
805            mapper.GetBoxId(field.GetValue(value))
806          );
807        }
808
809        foreach (var componentInfo in typeInfo.Properties.Where(x => x.Readable)) {
810          var property = (PropertyInfo)componentInfo.MemberInfo;
811          kvps.Add(
812            mapper.GetStringId(componentInfo.FullName),
813            mapper.GetBoxId(property.GetValue(value, null))
814          );
815        }
816
817        if (type != originalType) {
818          parentTypeVersions.AddRange(new[] { mapper.GetStringId(guid.ToString()), attribute.Version });
819        }
820
821        type = type.BaseType;
822      }
823    }
824
825    protected override object Extract(Box box, Type type, Mapper mapper) {
826      return mapper.CreateInstance(type);
827    }
828
829    public override void FillFromBox(object obj, Box box, Mapper mapper) {
830      var kvps = box.KeyValuePairs;
831      var parentTypeVersions = box.UInts;
832      var emptyArgs = new object[0];
833
834      var dict = new Dictionary<string, object>();
835      foreach (var entry in kvps) {
836        string key = mapper.GetString(entry.Key);
837        object value = mapper.GetObject(entry.Value);
838        dict.Add(key, value);
839      }
840
841      var type = (Type)mapper.GetObject(box.TypeBoxId);
842      var typeBox = mapper.GetBox(box.TypeBoxId);
843      var typeInfo = Mapper.StaticCache.GetTypeInfo(type);
844
845      var typeVersions = new List<Tuple<Guid, uint>>();
846      typeVersions.Add(Tuple.Create(typeInfo.StorableTypeAttribute.Guid, typeBox.TypeVersion));
847      for (int i = 0; i < parentTypeVersions.Count; i += 2)
848        typeVersions.Add(Tuple.Create(Guid.Parse(mapper.GetString(parentTypeVersions[i])), parentTypeVersions[i + 1]));
849
850      while (true) {
851        var applicableConversion = Mapper.StaticCache.GetStorableConversions(typeVersions).FirstOrDefault();
852        if (applicableConversion == null) break;
853
854        Dictionary<string, object> newDict;
855        List<Tuple<string, uint>> typeChain = null;
856
857        var conversionParameters = applicableConversion.GetParameters();
858        if (conversionParameters.Length == 1) {
859          newDict = (Dictionary<string, object>)applicableConversion.Invoke(null, new object[] { dict });
860        } else if (conversionParameters.Length == 2) {
861          var parameters = new object[] { dict, typeChain };
862          newDict = (Dictionary<string, object>)applicableConversion.Invoke(null, parameters);
863          typeChain = (List<Tuple<string, uint>>)parameters[1];
864        } else throw new PersistenceException("Conversion method has an invalid signature.");
865
866        foreach (var kvp in newDict) dict[kvp.Key] = kvp.Value;
867
868        var convertedType = StorableConversionAttribute.GetGuid(applicableConversion);
869        var convertedVersion = StorableConversionAttribute.GetVersion(applicableConversion);
870
871        var index = typeVersions.FindIndex(x => x.Item1 == convertedType);
872        typeVersions.RemoveAt(index);
873        typeVersions.Insert(index, Tuple.Create(convertedType, convertedVersion + 1));
874
875        if (typeChain != null && typeChain.Any()) {
876          typeVersions.RemoveRange(index + 1, typeVersions.Count - (index + 1));
877          typeVersions.AddRange(typeChain.Select(x => Tuple.Create(Guid.Parse(x.Item1), x.Item2)));
878        }
879      }
880
881      var typeStack = new Stack<Tuple<Type, TypeInfo>>();
882
883      while (StorableTypeAttribute.IsStorableType(type)) {
884        typeInfo = Mapper.StaticCache.GetTypeInfo(type);
885        typeStack.Push(Tuple.Create(type, typeInfo));
886        type = type.BaseType;
887      }
888
889      foreach (var frame in typeStack) {
890        type = frame.Item1;
891        typeInfo = frame.Item2;
892
893        // set default values for all fields and properties
894        foreach (var componentInfo in typeInfo.Fields) {
895          var attrib = componentInfo.StorableAttribute;
896          var fieldInfo = (FieldInfo)componentInfo.MemberInfo;
897          if (attrib != null && attrib.DefaultValue != null)
898            fieldInfo.SetValue(obj, attrib.DefaultValue);
899        }
900        foreach (var componentInfo in typeInfo.Properties.Where(x => x.Writeable)) {
901          var attrib = componentInfo.StorableAttribute;
902          var property = (PropertyInfo)componentInfo.MemberInfo;
903          if (attrib != null && attrib.DefaultValue != null)
904            property.SetValue(obj, attrib.DefaultValue, null);
905        }
906
907        // set all members as generated by conversion method chain
908        foreach (var kvp in dict) {
909          string key = kvp.Key;
910          object val = kvp.Value;
911
912          string[] keyParts = key.Split('.');
913          var guid = Guid.Parse(keyParts[0]);
914          string ident = keyParts[1];
915
916          if (guid != typeInfo.StorableTypeAttribute.Guid) continue;
917
918          var fieldInfo = typeInfo.Fields.FirstOrDefault(fi => fi.Name == ident);
919          if (fieldInfo != null) {
920            var field = (FieldInfo)fieldInfo.MemberInfo;
921            field.SetValue(obj, val);
922            //dict.Remove(guid.ToString().ToUpperInvariant() + "." + fieldInfo.Name); // only for consistency check
923            continue;
924          }
925
926          var propInfo = typeInfo.Properties.Where(x => x.Writeable).FirstOrDefault(fi => fi.Name == ident);
927          if (propInfo != null) {
928            var prop = (PropertyInfo)propInfo.MemberInfo;
929            prop.SetValue(obj, val, null);
930            //dict.Remove(guid.ToString().ToUpperInvariant() + "." + propInfo.Name); // only for consistency check
931            continue;
932          }
933        }
934
935        //var undefinedMembers = dict.Where(x => Guid.Parse(x.Key.Split('.')[0]) == typeInfo.StorableTypeAttribute.Guid);
936
937        //if (undefinedMembers.Any())
938        //  throw new PersistenceException(string.Format("Invalid conversion method. The following members are undefined in type {0} version {1}: {2}",
939        //    typeInfo.StorableTypeAttribute.Guid,
940        //    typeInfo.StorableTypeAttribute.Version,
941        //    string.Join(", ", undefinedMembers.Select(x => x.Key))));
942
943        foreach (var hook in typeInfo.AfterDeserializationHooks) {
944          hook.Invoke(obj, emptyArgs);
945        }
946      }
947    }
948  }
949}
Note: See TracBrowser for help on using the repository browser.