source: branches/PersistenceOverhaul/HeuristicLab.Persistence/4.0/Transformers/Transformers.cs @ 14711

Last change on this file since 14711 was 14711, checked in by gkronber, 2 years ago

#2520

  • renamed StorableClass -> StorableType
  • changed persistence to use GUIDs instead of type names
File size: 47.7 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.ComponentModel;
26using System.Drawing;
27using System.Drawing.Imaging;
28using System.Globalization;
29using System.IO;
30using System.Linq;
31using System.Reflection;
32using Google.ProtocolBuffers;
33using HeuristicLab.Persistence.Core;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35
36namespace HeuristicLab.Persistence {
37  public abstract class BoxTransformer<T> : Transformer {
38    public override bool CanTransformType(Type type) {
39      return type == typeof(T);
40    }
41
42    public override Box ToBox(object o, Mapper mapper) {
43      var box = Box.CreateBuilder();
44      box.TransformerId = mapper.GetTransformerId(this);
45      box.TypeId = mapper.GetBoxId(o.GetType());
46      Populate(box, (T)o, mapper);
47      return box.Build();
48    }
49    public override object ToObject(Box box, Mapper mapper) {
50      return Extract(box, (Type)mapper.GetObject(box.TypeId), mapper);
51    }
52    protected abstract void Populate(Box.Builder box, T value, Mapper mapper);
53    protected abstract T Extract(Box box, Type type, Mapper mapper);
54  }
55
56  #region Scalar Box Transformers
57  public abstract class BoolBoxTransformer<T> : BoxTransformer<T> {
58    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
59      var b = BoolBox.CreateBuilder();
60      b.Value = ToBoxType(value, mapper);
61      box.SetExtension<BoolBox>(BoolBox.Bool, b.Build());
62    }
63    protected override T Extract(Box box, Type type, Mapper mapper) {
64      return ToValueType(box.GetExtension(BoolBox.Bool).Value, type, mapper);
65    }
66    protected abstract bool ToBoxType(T value, Mapper mapper);
67    protected abstract T ToValueType(bool value, Type type, Mapper mapper);
68  }
69  public abstract class IntBoxTransformer<T> : BoxTransformer<T> {
70    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
71      var b = IntBox.CreateBuilder();
72      b.Value = ToBoxType(value, mapper);
73      box.SetExtension<IntBox>(IntBox.Int, b.Build());
74    }
75    protected override T Extract(Box box, Type type, Mapper mapper) {
76      return ToValueType(box.GetExtension(IntBox.Int).Value, type, mapper);
77    }
78    protected abstract int ToBoxType(T value, Mapper mapper);
79    protected abstract T ToValueType(int value, Type type, Mapper mapper);
80  }
81  public abstract class LongBoxTransformer<T> : BoxTransformer<T> {
82    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
83      var b = LongBox.CreateBuilder();
84      b.Value = ToBoxType(value, mapper);
85      box.SetExtension<LongBox>(LongBox.Long, b.Build());
86    }
87    protected override T Extract(Box box, Type type, Mapper mapper) {
88      return ToValueType(box.GetExtension(LongBox.Long).Value, type, mapper);
89    }
90    protected abstract long ToBoxType(T value, Mapper mapper);
91    protected abstract T ToValueType(long value, Type type, Mapper mapper);
92  }
93  public abstract class UnsignedIntBoxTransformer<T> : BoxTransformer<T> {
94    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
95      var b = UnsignedIntBox.CreateBuilder();
96      b.Value = ToBoxType(value, mapper);
97      box.SetExtension<UnsignedIntBox>(UnsignedIntBox.UnsignedInt, b.Build());
98    }
99    protected override T Extract(Box box, Type type, Mapper mapper) {
100      return ToValueType(box.GetExtension(UnsignedIntBox.UnsignedInt).Value, type, mapper);
101    }
102    protected abstract uint ToBoxType(T value, Mapper mapper);
103    protected abstract T ToValueType(uint value, Type type, Mapper mapper);
104  }
105  public abstract class UnsignedLongBoxTransformer<T> : BoxTransformer<T> {
106    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
107      var b = UnsignedLongBox.CreateBuilder();
108      b.Value = ToBoxType(value, mapper);
109      box.SetExtension<UnsignedLongBox>(UnsignedLongBox.UnsignedLong, b.Build());
110    }
111    protected override T Extract(Box box, Type type, Mapper mapper) {
112      return ToValueType(box.GetExtension(UnsignedLongBox.UnsignedLong).Value, type, mapper);
113    }
114    protected abstract ulong ToBoxType(T value, Mapper mapper);
115    protected abstract T ToValueType(ulong value, Type type, Mapper mapper);
116  }
117  public abstract class FloatBoxTransformer<T> : BoxTransformer<T> {
118    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
119      var b = FloatBox.CreateBuilder();
120      b.Value = ToBoxType(value, mapper);
121      box.SetExtension<FloatBox>(FloatBox.Float, b.Build());
122    }
123    protected override T Extract(Box box, Type type, Mapper mapper) {
124      return ToValueType(box.GetExtension(FloatBox.Float).Value, type, mapper);
125    }
126    protected abstract float ToBoxType(T value, Mapper mapper);
127    protected abstract T ToValueType(float value, Type type, Mapper mapper);
128  }
129  public abstract class DoubleBoxTransformer<T> : BoxTransformer<T> {
130    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
131      var b = DoubleBox.CreateBuilder();
132      b.Value = ToBoxType(value, mapper);
133      box.SetExtension<DoubleBox>(DoubleBox.Double, b.Build());
134    }
135    protected override T Extract(Box box, Type type, Mapper mapper) {
136      return ToValueType(box.GetExtension(DoubleBox.Double).Value, type, mapper);
137    }
138    protected abstract double ToBoxType(T value, Mapper mapper);
139    protected abstract T ToValueType(double value, Type type, Mapper mapper);
140  }
141  public abstract class StringBoxTransformer<T> : BoxTransformer<T> {
142    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
143      var b = StringBox.CreateBuilder();
144      b.Value = ToBoxType(value, mapper);
145      box.SetExtension<StringBox>(StringBox.String, b.Build());
146    }
147    protected override T Extract(Box box, Type type, Mapper mapper) {
148      return ToValueType(box.GetExtension(StringBox.String).Value, type, mapper);
149    }
150    protected abstract string ToBoxType(T value, Mapper mapper);
151    protected abstract T ToValueType(string value, Type type, Mapper mapper);
152  }
153  public abstract class BytesBoxTransformer<T> : BoxTransformer<T> {
154    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
155      var b = BytesBox.CreateBuilder();
156      b.Value = ByteString.CopyFrom(ToBoxType(value, mapper));
157      box.SetExtension<BytesBox>(BytesBox.Bytes, b.Build());
158    }
159    protected override T Extract(Box box, Type type, Mapper mapper) {
160      return ToValueType(box.GetExtension(BytesBox.Bytes).Value.ToByteArray(), type, mapper);
161    }
162    protected abstract byte[] ToBoxType(T value, Mapper mapper);
163    protected abstract T ToValueType(byte[] value, Type type, Mapper mapper);
164  }
165  #endregion
166
167  #region Array Box Transformers
168  public abstract class ByteArrayBoxTransformer<T> : BoxTransformer<T> {
169    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
170      var b = ByteArrayBox.CreateBuilder();
171      b.SetValues(ToByteString(value));
172      box.SetExtension(ByteArrayBox.ByteArray, b.Build());
173    }
174    protected override T Extract(Box box, Type type, Mapper mapper) {
175      return FromByteString(box.GetExtension(ByteArrayBox.ByteArray).Values);
176    }
177    protected abstract ByteString ToByteString(T value);
178    protected abstract T FromByteString(ByteString byteString);
179  }
180  public abstract class BoolArrayBoxTransformer<T> : BoxTransformer<T> {
181    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
182      var b = BoolArrayBox.CreateBuilder();
183      b.AddRangeValues(ToBoxType(value, mapper));
184      box.SetExtension<BoolArrayBox>(BoolArrayBox.BoolArray, b.Build());
185    }
186    protected override T Extract(Box box, Type type, Mapper mapper) {
187      return ToValueType(box.GetExtension(BoolArrayBox.BoolArray).ValuesList, type, mapper);
188    }
189    protected abstract IEnumerable<bool> ToBoxType(T value, Mapper mapper);
190    protected abstract T ToValueType(IEnumerable<bool> value, Type type, Mapper mapper);
191  }
192  public abstract class IntArrayBoxTransformer<T> : BoxTransformer<T> {
193    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
194      var b = IntArrayBox.CreateBuilder();
195      b.AddRangeValues(ToBoxType(value, mapper));
196      box.SetExtension<IntArrayBox>(IntArrayBox.IntArray, b.Build());
197    }
198    protected override T Extract(Box box, Type type, Mapper mapper) {
199      return ToValueType(box.GetExtension(IntArrayBox.IntArray).ValuesList, type, mapper);
200    }
201    protected abstract IEnumerable<int> ToBoxType(T value, Mapper mapper);
202    protected abstract T ToValueType(IEnumerable<int> value, Type type, Mapper mapper);
203  }
204  public abstract class LongArrayBoxTransformer<T> : BoxTransformer<T> {
205    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
206      var b = LongArrayBox.CreateBuilder();
207      b.AddRangeValues(ToBoxType(value, mapper));
208      box.SetExtension<LongArrayBox>(LongArrayBox.LongArray, b.Build());
209    }
210    protected override T Extract(Box box, Type type, Mapper mapper) {
211      return ToValueType(box.GetExtension(LongArrayBox.LongArray).ValuesList, type, mapper);
212    }
213    protected abstract IEnumerable<long> ToBoxType(T value, Mapper mapper);
214    protected abstract T ToValueType(IEnumerable<long> value, Type type, Mapper mapper);
215  }
216  public abstract class UnsignedIntArrayBoxTransformer<T> : BoxTransformer<T> {
217    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
218      var b = UnsignedIntArrayBox.CreateBuilder();
219      b.AddRangeValues(ToBoxType(value, mapper));
220      box.SetExtension<UnsignedIntArrayBox>(UnsignedIntArrayBox.UnsignedIntArray, b.Build());
221    }
222    protected override T Extract(Box box, Type type, Mapper mapper) {
223      return ToValueType(box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray).ValuesList, type, mapper);
224    }
225    protected abstract IEnumerable<uint> ToBoxType(T value, Mapper mapper);
226    protected abstract T ToValueType(IEnumerable<uint> value, Type type, Mapper mapper);
227  }
228  public abstract class UnsignedLongArrayBoxTransformer<T> : BoxTransformer<T> {
229    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
230      var b = UnsignedLongArrayBox.CreateBuilder();
231      b.AddRangeValues(ToBoxType(value, mapper));
232      box.SetExtension<UnsignedLongArrayBox>(UnsignedLongArrayBox.UnsignedLongArray, b.Build());
233    }
234    protected override T Extract(Box box, Type type, Mapper mapper) {
235      return ToValueType(box.GetExtension(UnsignedLongArrayBox.UnsignedLongArray).ValuesList, type, mapper);
236    }
237    protected abstract IEnumerable<ulong> ToBoxType(T value, Mapper mapper);
238    protected abstract T ToValueType(IEnumerable<ulong> value, Type type, Mapper mapper);
239  }
240  public abstract class FloatArrayBoxTransformer<T> : BoxTransformer<T> {
241    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
242      var b = FloatArrayBox.CreateBuilder();
243      b.AddRangeValues(ToBoxType(value, mapper));
244      box.SetExtension<FloatArrayBox>(FloatArrayBox.FloatArray, b.Build());
245    }
246    protected override T Extract(Box box, Type type, Mapper mapper) {
247      return ToValueType(box.GetExtension(FloatArrayBox.FloatArray).ValuesList, type, mapper);
248    }
249    protected abstract IEnumerable<float> ToBoxType(T value, Mapper mapper);
250    protected abstract T ToValueType(IEnumerable<float> value, Type type, Mapper mapper);
251  }
252  public abstract class DoubleArrayBoxTransformer<T> : BoxTransformer<T> {
253    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
254      var b = DoubleArrayBox.CreateBuilder();
255      b.AddRangeValues(ToBoxType(value, mapper));
256      box.SetExtension<DoubleArrayBox>(DoubleArrayBox.DoubleArray, b.Build());
257    }
258    protected override T Extract(Box box, Type type, Mapper mapper) {
259      return ToValueType(box.GetExtension(DoubleArrayBox.DoubleArray).ValuesList, type, mapper);
260    }
261    protected abstract IEnumerable<double> ToBoxType(T value, Mapper mapper);
262    protected abstract T ToValueType(IEnumerable<double> value, Type type, Mapper mapper);
263  }
264  public abstract class StringArrayBoxTransformer<T> : BoxTransformer<T> {
265    protected override void Populate(Box.Builder box, T value, Mapper mapper) {
266      var b = StringArrayBox.CreateBuilder();
267      b.AddRangeValues(ToBoxType(value, mapper));
268      box.SetExtension<StringArrayBox>(StringArrayBox.StringArray, b.Build());
269    }
270    protected override T Extract(Box box, Type type, Mapper mapper) {
271      return ToValueType(box.GetExtension(StringArrayBox.StringArray).ValuesList, type, mapper);
272    }
273    protected abstract IEnumerable<string> ToBoxType(T value, Mapper mapper);
274    protected abstract T ToValueType(IEnumerable<string> value, Type type, Mapper mapper);
275  }
276  #endregion
277
278  [Transformer("11B822C9-46A0-4B65-AE4A-D12F63DDE9F6", 50)]
279  internal sealed class TypeTransformer : Transformer {
280    public override bool CanTransformType(Type type) {
281      return typeof(Type).IsAssignableFrom(type);
282    }
283    public override Box ToBox(object o, Mapper mapper) {
284      var box = Box.CreateBuilder();
285      box.TransformerId = mapper.GetTransformerId(this);
286      Populate(box, o, mapper);
287      return box.Build();
288    }
289    private void Populate(Box.Builder box, object value, Mapper mapper) {
290      var type = (Type)value;
291      var typeBox = TypeBox.CreateBuilder();
292      if (type.IsGenericType) {
293        box.TypeId = mapper.GetTypeId(type.GetGenericTypeDefinition());
294        typeBox.AddRangeGenericTypeIds(type.GetGenericArguments().Select(t => mapper.GetBoxId(t)));
295      } else if (type.IsArray) {
296        box.TypeId = mapper.GetTypeId(typeof(Array));
297        typeBox.AddGenericTypeIds(mapper.GetBoxId(type.GetElementType()));
298      } else {
299        box.TypeId = mapper.GetTypeId(type);
300      }
301      box.SetExtension(TypeBox.Type, typeBox.Build());
302    }
303    public override object ToObject(Box box, Mapper mapper) {
304      return Extract(box, mapper.GetType(box.TypeId), mapper);
305    }
306    private object Extract(Box box, Type type, Mapper mapper) {
307      var b = box.GetExtension(TypeBox.Type);
308      if (type.IsGenericType) {
309        return type.MakeGenericType(b.GenericTypeIdsList.Select(id => (Type)mapper.GetObject(id)).ToArray());
310      } else if (type == typeof(Array)) {
311        return ((Type)mapper.GetObject(b.GetGenericTypeIds(0))).MakeArrayType();
312      } else {
313        return type;
314      }
315    }
316  }
317
318  #region Primitive Value Types
319  [Transformer("268617FE-3F0F-4029-8248-EDA420901FB6", 10000)]
320  internal sealed class ObjectTransformer : BoxTransformer<object> {
321    protected override void Populate(Box.Builder box, object value, Mapper mapper) { }
322    protected override object Extract(Box box, Type type, Mapper mapper) { return new object(); }
323  }
324
325  [Transformer("9FA1C6A8-517E-4623-AC1B-7E9AEF6ED13D", 200)]
326  internal sealed class BoolTransformer : BoolBoxTransformer<bool> {
327    protected override bool ToBoxType(bool value, Mapper mapper) { return value; }
328    protected override bool ToValueType(bool value, Type type, Mapper mapper) { return value; }
329  }
330
331  [Transformer("059633E9-12CB-43EC-8544-57746536E281", 201)]
332  internal sealed class ByteTransformer : UnsignedIntBoxTransformer<byte> {
333    protected override uint ToBoxType(byte value, Mapper mapper) { return value; }
334    protected override byte ToValueType(uint value, Type type, Mapper mapper) { return (byte)value; }
335  }
336
337  [Transformer("5DC2F3AC-0852-4B57-A861-D29CC814A94C", 202)]
338  internal sealed class SByteTransformer : IntBoxTransformer<sbyte> {
339    protected override int ToBoxType(sbyte value, Mapper mapper) { return value; }
340    protected override sbyte ToValueType(int value, Type type, Mapper mapper) { return (sbyte)value; }
341  }
342
343  [Transformer("B862E642-A94A-4870-8065-06126A35A9E1", 203)]
344  internal sealed class ShortTransformer : IntBoxTransformer<short> {
345    protected override int ToBoxType(short value, Mapper mapper) { return value; }
346    protected override short ToValueType(int value, Type type, Mapper mapper) { return (short)value; }
347  }
348
349  [Transformer("D1D3062D-F1BB-4189-AE50-D6986E1DEB4E", 204)]
350  internal sealed class UShortTransformer : UnsignedIntBoxTransformer<ushort> {
351    protected override uint ToBoxType(ushort value, Mapper mapper) { return value; }
352    protected override ushort ToValueType(uint value, Type type, Mapper mapper) { return (ushort)value; }
353  }
354
355  [Transformer("6C444645-3062-4D15-AD01-E6E1B0692A2B", 205)]
356  internal sealed class CharTransformer : UnsignedIntBoxTransformer<char> {
357    protected override uint ToBoxType(char value, Mapper mapper) { return value; }
358    protected override char ToValueType(uint value, Type type, Mapper mapper) { return (char)value; }
359  }
360
361  [Transformer("649E73B2-EFA6-4E01-BCB4-4B29D652C9CB", 206)]
362  internal sealed class IntTransformer : IntBoxTransformer<int> {
363    protected override int ToBoxType(int value, Mapper mapper) { return value; }
364    protected override int ToValueType(int value, Type type, Mapper mapper) { return value; }
365  }
366
367  [Transformer("BCF25010-81A2-49BC-88CC-407D3F393D5B", 207)]
368  internal sealed class UIntTransformer : UnsignedIntBoxTransformer<uint> {
369    protected override uint ToBoxType(uint value, Mapper mapper) { return value; }
370    protected override uint ToValueType(uint value, Type type, Mapper mapper) { return value; }
371  }
372
373  [Transformer("B6F6ACAE-755C-47EE-B8BF-7CDECBE19C30", 208)]
374  internal sealed class LongTransformer : LongBoxTransformer<long> {
375    protected override long ToBoxType(long value, Mapper mapper) { return value; }
376    protected override long ToValueType(long value, Type type, Mapper mapper) { return value; }
377  }
378
379  [Transformer("82333ACA-F041-44E0-B365-27C399594BA7", 209)]
380  internal sealed class ULongTransformer : UnsignedLongBoxTransformer<ulong> {
381    protected override ulong ToBoxType(ulong value, Mapper mapper) { return value; }
382    protected override ulong ToValueType(ulong value, Type type, Mapper mapper) { return value; }
383  }
384
385  [Transformer("8FE91ECF-2261-4934-BECD-C38923B7A703", 210)]
386  internal sealed class FloatTransformer : FloatBoxTransformer<float> {
387    protected override float ToBoxType(float value, Mapper mapper) { return value; }
388    protected override float ToValueType(float value, Type type, Mapper mapper) { return value; }
389  }
390
391  [Transformer("070D23EA-7F38-46B7-A667-219BEF914E49", 211)]
392  internal sealed class DoubleTransformer : DoubleBoxTransformer<double> {
393    protected override double ToBoxType(double value, Mapper mapper) { return value; }
394    protected override double ToValueType(double value, Type type, Mapper mapper) { return value; }
395  }
396
397  [Transformer("BA55C7A6-C91E-4351-A889-E4A7E647F16D", 212)]
398  internal sealed class DateTimeTransformer : LongBoxTransformer<DateTime> {
399    protected override long ToBoxType(DateTime value, Mapper mapper) { return value.Ticks; }
400    protected override DateTime ToValueType(long value, Type type, Mapper mapper) { return new DateTime(value); }
401  }
402
403  [Transformer("0C91441B-2D97-432B-B493-D6EC483FC5AD", 213)]
404  internal sealed class TimeSpanTransformer : LongBoxTransformer<TimeSpan> {
405    protected override long ToBoxType(TimeSpan value, Mapper mapper) { return value.Ticks; }
406    protected override TimeSpan ToValueType(long value, Type type, Mapper mapper) { return new TimeSpan(value); }
407  }
408
409  [Transformer("0B540EAC-79AB-40CF-8277-D2C81135FEB6", 214)]
410  internal sealed class ColorTransformers : IntBoxTransformer<Color> {
411    protected override int ToBoxType(Color value, Mapper mapper) { return value.ToArgb(); }
412    protected override Color ToValueType(int value, Type type, Mapper mapper) { return Color.FromArgb(value); }
413  }
414
415  [Transformer("2E6D4A40-B4BE-425F-8E35-2D7C00054639", 215)]
416  internal sealed class PointTransformer : IntArrayBoxTransformer<Point> {
417    protected override IEnumerable<int> ToBoxType(Point value, Mapper mapper) { return new int[] { value.X, value.Y }; }
418    protected override Point ToValueType(IEnumerable<int> value, Type type, Mapper mapper) { return new Point(value.ElementAt(0), value.ElementAt(1)); }
419  }
420
421  [Transformer("97B5CFC8-CDFA-4EB5-B4CD-5B3CFA5CD844", 216)]
422  internal sealed class KeyValuePairTransformer : BoxTransformer<object> {
423    public override bool CanTransformType(Type type) {
424      return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
425    }
426    protected override void Populate(Box.Builder box, object value, Mapper mapper) {
427      var b = UnsignedIntArrayBox.CreateBuilder();
428      var type = value.GetType();
429      var pair = new uint[2];
430      pair[0] = mapper.GetBoxId(type.GetProperty("Key").GetValue(value));
431      pair[1] = mapper.GetBoxId(type.GetProperty("Value").GetValue(value));
432      b.AddRangeValues(pair);
433      box.SetExtension(UnsignedIntArrayBox.UnsignedIntArray, b.Build());
434    }
435    public override void FillFromBox(object obj, Box box, Mapper mapper) {
436      var b = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
437      var key = mapper.GetObject(b.GetValues(0));
438      var val = mapper.GetObject(b.GetValues(1));
439      var type = obj.GetType();
440      //DataMemberAccessor.GenerateFieldSetter(type.GetField("key", BindingFlags.NonPublic | BindingFlags.Instance))(obj, key);
441      //DataMemberAccessor.GenerateFieldSetter(type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance))(obj, val);
442      type.GetField("key", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(obj, key);
443      type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(obj, val);
444    }
445    protected override object Extract(Box box, Type type, Mapper mapper) {
446      return Activator.CreateInstance(type);
447    }
448  }
449
450  [Transformer("EBD8BF65-D97D-4FD4-BF4F-9D58A72B6249", 217)]
451  internal sealed class DecimalTransformer : UnsignedIntBoxTransformer<decimal> {
452    protected override uint ToBoxType(decimal value, Mapper mapper) {
453      return mapper.GetStringId(FormatG30(value));
454    }
455    protected override decimal ToValueType(uint value, Type type, Mapper mapper) {
456      var converter = TypeDescriptor.GetConverter(typeof(Font));
457      return ParseG30(mapper.GetString(value));
458    }
459    private static decimal ParseG30(string s) {
460      decimal d;
461      if (decimal.TryParse(s,
462        NumberStyles.AllowDecimalPoint |
463        NumberStyles.AllowExponent |
464        NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out d))
465        return d;
466      throw new FormatException(
467        string.Format("Invalid decimal G30 number format \"{0}\" could not be parsed", s));
468    }
469    private static string FormatG30(decimal d) {
470      return d.ToString("g30", CultureInfo.InvariantCulture);
471    }
472  }
473  #endregion
474
475  #region String
476  [Transformer("E75A594C-0034-4DAB-B28E-8F84F9F6DE8D", 218)]
477  internal sealed class StringTransformer : UnsignedIntBoxTransformer<string> {
478    protected override uint ToBoxType(string value, Mapper mapper) { return mapper.GetStringId(value); }
479    protected override string ToValueType(uint value, Type type, Mapper mapper) { return mapper.GetString(value); }
480  }
481  #endregion
482
483  #region Enum
484  [Transformer("93FF076B-BC4B-4C39-8C40-15E004468C98", 219)]
485  internal sealed class EnumTransformer : Transformer {
486    public override bool CanTransformType(Type type) {
487      return typeof(Enum).IsAssignableFrom(type);
488    }
489
490    public override Box ToBox(object o, Mapper mapper) {
491      var boxBuilder = Box.CreateBuilder();
492      var enumBuilder = new UnsignedIntBox.Builder();
493
494      boxBuilder.TransformerId = mapper.GetTransformerId(this);
495      boxBuilder.TypeId = mapper.GetStringId(o.GetType().AssemblyQualifiedName);
496      enumBuilder.Value = mapper.GetStringId(Enum.Format(o.GetType(), o, "G"));
497
498      boxBuilder.SetExtension(UnsignedIntBox.UnsignedInt, enumBuilder.Build());
499      return boxBuilder.Build();
500    }
501
502    public override object ToObject(Box box, Mapper mapper) {
503      uint value = box.GetExtension(UnsignedIntBox.UnsignedInt).Value;
504      return Enum.Parse(Type.GetType(mapper.GetString(box.TypeId)), mapper.GetString(value));
505    }
506  }
507  #endregion
508
509  #region Struct
510  [Transformer("89DAAFC5-726C-48D4-A4E0-2B0D27329642", 220)]
511  internal sealed class StructTransformer : Transformer {
512    public override bool CanTransformType(Type type) {
513      return type.IsValueType && !type.IsPrimitive && !type.IsEnum && type.IsSealed;
514    }
515    public override Box ToBox(object o, Mapper mapper) {
516      var box = Box.CreateBuilder();
517      box.TransformerId = mapper.GetTransformerId(this);
518      Populate(box, o, mapper);
519      return box.Build();
520    }
521    public override object ToObject(Box box, Mapper mapper) {
522      return Extract(box, (Type)mapper.GetObject(box.TypeId), mapper);
523    }
524    private void Populate(Box.Builder box, object value, Mapper mapper) {
525      var b = StorableClassBox.CreateBuilder();
526      var type = value.GetType();
527
528      var components = new Dictionary<uint, uint>();
529      foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
530        var component = mapper.GetBoxId(fieldInfo.GetValue(value));
531        components.Add(mapper.GetStringId(fieldInfo.Name), component);
532      }
533
534      b.AddRangeKeyIds(components.Keys);
535      b.AddRangeValueIds(components.Values);
536
537      box.TypeId = mapper.GetBoxId(type);
538      box.SetExtension(StorableClassBox.StorableClass, b.Build());
539    }
540    private object Extract(Box box, Type type, Mapper mapper) {
541      var data = box.GetExtension(StorableClassBox.StorableClass);
542      var obj = Activator.CreateInstance(type);
543
544      var components = new Dictionary<uint, uint>();
545      for (int i = 0; i < data.KeyIdsList.Count; i++) {
546        components.Add(data.KeyIdsList[i], data.ValueIdsList[i]);
547      }
548
549      foreach (var t in components) {
550        string name = mapper.GetString(t.Key);
551        MemberInfo[] mis = type.GetMember(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);       
552        if (mis.Length != 1)
553          throw new Exception("ambiguous struct member name " + name);
554        MemberInfo mi = mis[0];
555        if(StorableAttribute.IsStorable(mi))
556          throw new PersistenceException("Don't use stroable attributes for structs as all fields are serialized automatically.");
557        if (mi.MemberType == MemberTypes.Field)
558          ((FieldInfo)mi).SetValue(obj, mapper.GetObject(t.Value));
559        else
560          throw new Exception("invalid struct member type " + mi.MemberType.ToString());
561      }
562
563      return obj;
564    }
565  }
566  #endregion
567
568  #region Tuple
569  [Transformer("63A19D57-EEEF-4346-9F06-B35B15EBFFA3", 221)]
570  internal sealed class TupleTransformer : Transformer {
571    private static readonly HashSet<Type> supportedTypes = new HashSet<Type> {
572      typeof(Tuple<>), typeof(Tuple<,>), typeof(Tuple<,,>), typeof(Tuple<,,,>),
573      typeof(Tuple<,,,,>), typeof(Tuple<,,,,,>), typeof(Tuple<,,,,,,>), typeof(Tuple<,,,,,,,>)
574    };
575    public override bool CanTransformType(Type type) {
576      return type.IsGenericType && supportedTypes.Contains(type.GetGenericTypeDefinition());
577    }
578    public override Box ToBox(object o, Mapper mapper) {
579      var box = Box.CreateBuilder();
580      box.TransformerId = mapper.GetTransformerId(this);
581      Populate(box, o, mapper);
582      return box.Build();
583    }
584    private void Populate(Box.Builder box, object value, Mapper mapper) {
585      var type = value.GetType();
586      var uIntArrayBox = UnsignedIntArrayBox.CreateBuilder();
587      for (int i = 1; i <= type.GetGenericArguments().Length; i++) {
588        string name = string.Format("Item{0}", i);
589        uIntArrayBox.AddValues(mapper.GetBoxId(type.GetProperty(name).GetValue(value)));
590      }
591      box.TypeId = mapper.GetBoxId(type);
592      box.SetExtension(UnsignedIntArrayBox.UnsignedIntArray, uIntArrayBox.Build());
593    }
594    public override object ToObject(Box box, Mapper mapper) {
595      var type = (Type)mapper.GetObject(box.TypeId);
596      var defaultValues = type.GetGenericArguments().Select(x =>
597        x.IsValueType ? Activator.CreateInstance(x) : null
598      ).ToArray();
599      return Activator.CreateInstance(type, defaultValues);
600    }
601    public override void FillFromBox(object obj, Box box, Mapper mapper) {
602      var uIntArrayBox = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
603      var elements = uIntArrayBox.ValuesList.Select(mapper.GetObject).ToArray();
604      var type = obj.GetType();
605      for (int i = 1; i <= elements.Length; i++) {
606        string name = string.Format("m_Item{0}", i);
607        DataMemberAccessor.GenerateFieldSetter(type.GetField(name, BindingFlags.NonPublic | BindingFlags.Instance))(obj, elements[i - 1]);
608      }
609    }
610  }
611  #endregion
612
613  #region Bitmap
614  [Transformer("D0ADB806-2DFD-459D-B5DA-14B5F1152534", 222)]
615  internal sealed class BitmapTransformer : ByteArrayBoxTransformer<Bitmap> {
616    protected override ByteString ToByteString(Bitmap value) {
617      lock (value)
618        using (var ms = new MemoryStream()) {
619          value.Save(ms, ImageFormat.Png);
620          return ByteString.CopyFrom(ms.ToArray());
621        }
622    }
623    protected override Bitmap FromByteString(ByteString byteString) {
624      using (var ms = new MemoryStream()) {
625        ms.Write(byteString.ToArray(), 0, byteString.Length);
626        ms.Seek(0, SeekOrigin.Begin);
627        return new Bitmap(ms);
628      }
629    }
630  }
631  #endregion
632
633  #region Font
634  [Transformer("AFF27987-3301-4D70-9601-EFCA31BDA0DB", 223)]
635  internal sealed class FontTransformer : UnsignedIntArrayBoxTransformer<Font> {
636
637    protected override IEnumerable<uint> ToBoxType(Font value, Mapper mapper) {
638      yield return mapper.GetStringId(GetFontFamilyName(value.FontFamily));
639      yield return mapper.GetBoxId(value.Size);
640      yield return mapper.GetBoxId(value.Style);
641      yield return mapper.GetBoxId(value.Unit);
642      yield return mapper.GetBoxId(value.GdiCharSet);
643      yield return mapper.GetBoxId(value.GdiVerticalFont);
644    }
645    protected override Font ToValueType(IEnumerable<uint> value, Type type, Mapper mapper) {
646      var fontData = value.ToArray();
647      return new Font(
648        GetFontFamily(mapper.GetString(fontData[0])),
649        (float)mapper.GetObject(fontData[1]),
650        (FontStyle)mapper.GetObject(fontData[2]),
651        (GraphicsUnit)mapper.GetObject(fontData[3]),
652        (byte)mapper.GetObject(fontData[4]),
653        (bool)mapper.GetObject(fontData[5])
654      );
655    }
656
657    public const string GENERIC_MONOSPACE_NAME = "_GenericMonospace";
658    public const string GENERIC_SANS_SERIF_NAME = "_GenericSansSerif";
659    public const string GENERIC_SERIF_NAME = "_GenericSerif";
660
661    public static FontFamily GetFontFamily(string name) {
662      if (name == GENERIC_MONOSPACE_NAME) return FontFamily.GenericMonospace;
663      if (name == GENERIC_SANS_SERIF_NAME) return FontFamily.GenericSansSerif;
664      if (name == GENERIC_SERIF_NAME) return FontFamily.GenericSerif;
665      return new FontFamily(name);
666    }
667
668    public static string GetFontFamilyName(FontFamily ff) {
669      if (ff.Equals(FontFamily.GenericMonospace)) return GENERIC_MONOSPACE_NAME;
670      if (ff.Equals(FontFamily.GenericSansSerif)) return GENERIC_SANS_SERIF_NAME;
671      if (ff.Equals(FontFamily.GenericSerif)) return GENERIC_SERIF_NAME;
672      return ff.Name;
673    }
674  }
675  #endregion
676
677  #region Array Types
678  [Transformer("FF89F6D1-CDE3-498E-9166-F70AC6EB01F1", 301)]
679  internal sealed class ByteArrayTransformer : ByteArrayBoxTransformer<byte[]> {
680    protected override ByteString ToByteString(byte[] value) {
681      return ByteString.CopyFrom(value);
682    }
683    protected override byte[] FromByteString(ByteString byteString) {
684      return byteString.ToArray();
685    }
686  }
687
688  [Transformer("B49B3F2D-2E97-4BAB-8705-8D29DA707C6A", 302)]
689  internal sealed class SByteArrayTransformer : ByteArrayBoxTransformer<sbyte[]> {
690    protected override ByteString ToByteString(sbyte[] value) {
691      return ByteString.CopyFrom(value.Select(b => (byte)b).ToArray());
692    }
693    protected override sbyte[] FromByteString(ByteString byteString) {
694      return byteString.Select(b => (sbyte)b).ToArray();
695    }
696  }
697
698  [Transformer("F25A73B2-6B67-4493-BD59-B836AF4455D1", 300)]
699  internal sealed class BoolArrayTransformer : BoolArrayBoxTransformer<bool[]> {
700    protected override IEnumerable<bool> ToBoxType(bool[] value, Mapper mapper) { return value; }
701    protected override bool[] ToValueType(IEnumerable<bool> value, Type type, Mapper mapper) { return value.ToArray(); }
702  }
703
704  [Transformer("2811FDD4-6800-4CBA-86D7-9071ED5775ED", 303)]
705  internal sealed class ShortArrayTransformer : ByteArrayBoxTransformer<short[]> {
706    protected override ByteString ToByteString(short[] value) {
707      var res = new byte[value.Length * 2];
708      for (int i = 0; i < value.Length; i++) {
709        var bytes = BitConverter.GetBytes(value[i]);
710        Array.Copy(bytes, 0, res, i * 2, 2);
711      }
712      return ByteString.CopyFrom(res);
713    }
714    protected override short[] FromByteString(ByteString byteString) {
715      var bytes = byteString.ToArray();
716      var res = new short[bytes.Length / 2];
717      for (int i = 0; i < bytes.Length; i += 2) {
718        res[i / 2] = BitConverter.ToInt16(bytes, i);
719      }
720      return res;
721    }
722  }
723
724  [Transformer("1AAC2625-356C-40BC-8CB4-15CB3D047EB8", 304)]
725  internal sealed class UShortArrayTransformer : ByteArrayBoxTransformer<ushort[]> {
726    protected override ByteString ToByteString(ushort[] value) {
727      var res = new byte[value.Length * 2];
728      for (int i = 0; i < value.Length; i++) {
729        var bytes = BitConverter.GetBytes(value[i]);
730        Array.Copy(bytes, 0, res, i * 2, 2);
731      }
732      return ByteString.CopyFrom(res);
733    }
734    protected override ushort[] FromByteString(ByteString byteString) {
735      var bytes = byteString.ToArray();
736      var res = new ushort[bytes.Length / 2];
737      for (int i = 0; i < bytes.Length; i += 2) {
738        res[i / 2] = BitConverter.ToUInt16(bytes, i);
739      }
740      return res;
741    }
742  }
743
744  [Transformer("12F19098-5D49-4C23-8897-69087F1C146D", 305)]
745  internal sealed class CharArrayTransformer : ByteArrayBoxTransformer<char[]> {
746    protected override ByteString ToByteString(char[] value) {
747      var res = new byte[value.Length * 2];
748      for (int i = 0; i < value.Length; i++) {
749        var bytes = BitConverter.GetBytes(value[i]);
750        Array.Copy(bytes, 0, res, i * 2, 2);
751      }
752      return ByteString.CopyFrom(res);
753    }
754    protected override char[] FromByteString(ByteString byteString) {
755      var bytes = byteString.ToArray();
756      var res = new char[bytes.Length / 2];
757      for (int i = 0; i < bytes.Length; i += 2) {
758        res[i / 2] = BitConverter.ToChar(bytes, i);
759      }
760      return res;
761    }
762  }
763
764  [Transformer("5F6DC3BC-4433-4AE9-A636-4BD126F7DACD", 306)]
765  internal sealed class IntArrayTransformer : IntArrayBoxTransformer<int[]> {
766    protected override IEnumerable<int> ToBoxType(int[] value, Mapper mapper) { return value; }
767    protected override int[] ToValueType(IEnumerable<int> value, Type type, Mapper mapper) { return value.ToArray(); }
768  }
769
770  [Transformer("3F10274F-D350-4C82-89EA-A5EB36D4EFCC", 307)]
771  internal sealed class UIntArrayTransformer : UnsignedIntArrayBoxTransformer<uint[]> {
772    protected override IEnumerable<uint> ToBoxType(uint[] value, Mapper mapper) { return value; }
773    protected override uint[] ToValueType(IEnumerable<uint> value, Type type, Mapper mapper) { return value.ToArray(); }
774  }
775
776  [Transformer("E9D550E2-57F7-47F3-803D-37A619DA1A5C", 308)]
777  internal sealed class LongArrayTransformer : LongArrayBoxTransformer<long[]> {
778    protected override IEnumerable<long> ToBoxType(long[] value, Mapper mapper) { return value; }
779    protected override long[] ToValueType(IEnumerable<long> value, Type type, Mapper mapper) { return value.ToArray(); }
780  }
781
782  [Transformer("C02A205B-2176-4282-AC2B-ADEF96DDBE24", 309)]
783  internal sealed class ULongArrayTransformer : UnsignedLongArrayBoxTransformer<ulong[]> {
784    protected override IEnumerable<ulong> ToBoxType(ulong[] value, Mapper mapper) { return value; }
785    protected override ulong[] ToValueType(IEnumerable<ulong> value, Type type, Mapper mapper) { return value.ToArray(); }
786  }
787
788  [Transformer("3C4590D9-C76E-4AFB-98FD-E50D3D051648", 310)]
789  internal sealed class FloatArrayTransformer : FloatArrayBoxTransformer<float[]> {
790    protected override IEnumerable<float> ToBoxType(float[] value, Mapper mapper) { return value; }
791    protected override float[] ToValueType(IEnumerable<float> value, Type type, Mapper mapper) { return value.ToArray(); }
792  }
793
794  [Transformer("FB98C399-9323-4470-9A85-9186C2B2D5D4", 311)]
795  internal sealed class DoubleArrayTransformer : DoubleArrayBoxTransformer<double[]> {
796    protected override IEnumerable<double> ToBoxType(double[] value, Mapper mapper) { return value; }
797    protected override double[] ToValueType(IEnumerable<double> value, Type type, Mapper mapper) { return value.ToArray(); }
798  }
799
800  [Transformer("68332513-9CF1-47FA-A093-6DDB663186EC", 312)]
801  internal sealed class StringArrayTransformer : StringArrayBoxTransformer<string[]> {
802    protected override IEnumerable<string> ToBoxType(string[] value, Mapper mapper) { return value; }
803    protected override string[] ToValueType(IEnumerable<string> value, Type type, Mapper mapper) { return value.ToArray(); }
804  }
805
806  [Transformer("B01ADF0A-ACAA-444E-9F82-0C7C2AF1F490", 400)]
807  internal sealed class ArrayTransformer : Transformer {
808    public override bool CanTransformType(Type type) {
809      return type.IsArray;
810    }
811    public override Box ToBox(object o, Mapper mapper) {
812      var box = Box.CreateBuilder();
813      box.TransformerId = mapper.GetTransformerId(this);
814      Populate(box, o, mapper);
815      return box.Build();
816    }
817    private void Populate(Box.Builder box, object value, Mapper mapper) {
818      var type = value.GetType();
819      var array = (Array)value;
820      var rank = array.Rank;
821
822      var uIntArrayBox = UnsignedIntArrayBox.CreateBuilder();
823      uIntArrayBox.AddValues(mapper.GetBoxId(rank));
824
825      int[] lengths = new int[rank];
826      int[] lowerBounds = new int[rank];
827      for (int i = 0; i < rank; i++) {
828        lengths[i] = array.GetLength(i);
829        lowerBounds[i] = array.GetLowerBound(i);
830      }
831
832      uIntArrayBox.AddRangeValues(lengths.Select(x => mapper.GetBoxId(x)));
833      uIntArrayBox.AddRangeValues(lowerBounds.Select(x => mapper.GetBoxId(x)));
834
835      int[] positions = (int[])lowerBounds.Clone();
836      while (positions[rank - 1] < lengths[rank - 1] + lowerBounds[rank - 1]) {
837        uIntArrayBox.AddValues(mapper.GetBoxId(array.GetValue(positions)));
838        positions[0] += 1;
839        for (int i = 0; i < rank - 1; i++) {
840          if (positions[i] >= lowerBounds[i] + lengths[i]) {
841            positions[i] = lowerBounds[i];
842            positions[i + 1] += 1;
843          } else {
844            break;
845          }
846        }
847      }
848
849      box.TypeId = mapper.GetBoxId(type);
850      box.SetExtension(UnsignedIntArrayBox.UnsignedIntArray, uIntArrayBox.Build());
851    }
852    public override object ToObject(Box box, Mapper mapper) {
853      var uIntArrayBox = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
854      var rank = (int)mapper.GetObject(uIntArrayBox.GetValues(0));
855
856      int[] lengths = new int[rank], lowerBounds = new int[rank];
857      for (int i = 0; i < rank; i++)
858        lengths[i] = (int)mapper.GetObject(uIntArrayBox.GetValues(i + 1));
859      for (int i = 0; i < rank; i++)
860        lowerBounds[i] = (int)mapper.GetObject(uIntArrayBox.GetValues(i + 1 + rank));
861
862      var type = (Type)mapper.GetObject(box.TypeId);
863      return Array.CreateInstance(type.GetElementType(), lengths, lowerBounds);
864    }
865    public override void FillFromBox(object obj, Box box, Mapper mapper) {
866      var array = (Array)obj;
867      var uIntArrayBox = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
868      var rank = (int)mapper.GetObject(uIntArrayBox.GetValues(0));
869
870      int[] lengths = new int[rank], lowerBounds = new int[rank];
871      for (int i = 0; i < rank; i++)
872        lengths[i] = (int)mapper.GetObject(uIntArrayBox.GetValues(i + 1));
873      for (int i = 0; i < rank; i++)
874        lowerBounds[i] = (int)mapper.GetObject(uIntArrayBox.GetValues(i + 1 + rank));
875
876      int[] positions = (int[])lowerBounds.Clone();
877      var e = uIntArrayBox.ValuesList.Skip(1 + 2 * rank).GetEnumerator();
878      while (e.MoveNext()) {
879        int[] currentPositions = positions;
880        array.SetValue(mapper.GetObject(e.Current), currentPositions);
881        positions[0] += 1;
882        for (int i = 0; i < rank - 1; i++) {
883          if (positions[i] >= lengths[i] + lowerBounds[i]) {
884            positions[i] = lowerBounds[i];
885            positions[i + 1] += 1;
886          } else {
887            break;
888          }
889        }
890      }
891    }
892  }
893  #endregion
894
895  [Transformer("4FA5EAAF-ECC7-4A9C-84E7-6583DA96F3B9", 500)]
896  internal sealed class EnumerableTransformer : Transformer {
897    private static readonly HashSet<Type> supportedTypes = new HashSet<Type> {
898      typeof(Stack<>), typeof(Stack),
899      typeof(Queue<>), typeof(Queue),
900      typeof(HashSet<>),
901      typeof(List<>), typeof(ArrayList)
902    };
903    public override bool CanTransformType(Type type) {
904      return type.IsGenericType && supportedTypes.Contains(type.GetGenericTypeDefinition()) || supportedTypes.Contains(type);
905    }
906    public override Box ToBox(object o, Mapper mapper) {
907      var box = Box.CreateBuilder();
908      box.TransformerId = mapper.GetTransformerId(this);
909      Populate(box, o, mapper);
910      return box.Build();
911    }
912    private void Populate(Box.Builder box, object value, Mapper mapper) {
913      var uIntArrayBox = UnsignedIntArrayBox.CreateBuilder();
914
915      var type = value.GetType();
916      var propertyInfo = type.GetProperty("Comparer");
917      if (propertyInfo != null) {
918        // TODO: where to store id for comparer box? (atm: first element in int array ...)
919        var comparer = propertyInfo.GetValue(value);
920        var comparerType = comparer.GetType();
921        if (Default.CompositeSerializers.Storable.StorableTypeAttribute.IsStorableType(comparerType))
922          uIntArrayBox.AddValues(mapper.GetBoxId(comparer));
923        else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
924          throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
925        else
926          uIntArrayBox.AddValues(mapper.GetBoxId(comparerType));
927      }
928
929      foreach (var item in (IEnumerable)value)
930        uIntArrayBox.AddValues(mapper.GetBoxId(item));
931
932      box.TypeId = mapper.GetBoxId(type);
933      box.SetExtension(UnsignedIntArrayBox.UnsignedIntArray, uIntArrayBox.Build());
934    }
935    public override object ToObject(Box box, Mapper mapper) {
936      var uIntArrayBox = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
937      var type = (Type)mapper.GetObject(box.TypeId);
938      return Activator.CreateInstance(type);
939    }
940    public override void FillFromBox(object obj, Box box, Mapper mapper) {
941      var uIntArrayBox = box.GetExtension(UnsignedIntArrayBox.UnsignedIntArray);
942      var elements = uIntArrayBox.ValuesList.Select(mapper.GetObject);
943      var type = obj.GetType();
944
945      string methodName = string.Empty;
946      if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Stack<>) || type == typeof(Stack)) {
947        elements = elements.Reverse();
948        methodName = "Push";
949      } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Queue<>) || type == typeof(Queue)) {
950        methodName = "Enqueue";
951      } else {
952        methodName = "Add";
953        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>)) {
954          var fieldInfo = type.GetField("m_comparer", BindingFlags.NonPublic | BindingFlags.Instance);
955          var comparerObj = mapper.GetObject(uIntArrayBox.GetValues(0));
956          var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
957          fieldInfo.SetValue(obj, comparer);
958          elements = elements.Skip(1);
959        }
960      }
961
962      MethodInfo addMethod = type.GetMethod(methodName);
963      foreach (var e in elements)
964        addMethod.Invoke(obj, new[] { e });
965    }
966  }
967
968  [Transformer("C47A62F5-F113-4A43-A8EE-CF817EC799A2", 501)]
969  internal sealed class DictionaryTransformer : Transformer {
970    public override bool CanTransformType(Type type) {
971      return type.IsGenericType && typeof(Dictionary<,>) == type.GetGenericTypeDefinition();
972    }
973    public override Box ToBox(object o, Mapper mapper) {
974      var box = Box.CreateBuilder();
975      box.TransformerId = mapper.GetTransformerId(this);
976      Populate(box, o, mapper);
977      return box.Build();
978    }
979    private void Populate(Box.Builder box, object value, Mapper mapper) {
980      var dictionaryBox = DictionaryBox.CreateBuilder();
981      foreach (DictionaryEntry item in (IDictionary)value) {
982        dictionaryBox.AddKeyIds(mapper.GetBoxId(item.Key));
983        dictionaryBox.AddValueIds(mapper.GetBoxId(item.Value));
984      }
985
986      var type = value.GetType();
987      var propertyInfo = type.GetProperty("Comparer");
988      var comparer = propertyInfo.GetValue(value);
989
990      var comparerType = comparer.GetType();
991      if (Default.CompositeSerializers.Storable.StorableTypeAttribute.IsStorableType(comparerType))
992        dictionaryBox.SetComparerId(mapper.GetBoxId(comparer));
993      else if (comparerType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Any())
994        throw new NotSupportedException("Cannot serialize non-storable equality comparers with fields");
995      else
996        dictionaryBox.SetComparerId(mapper.GetBoxId(comparerType));
997
998      box.TypeId = mapper.GetBoxId(type);
999      box.SetExtension(DictionaryBox.Dictionary, dictionaryBox.Build());
1000    }
1001    public override object ToObject(Box box, Mapper mapper) {
1002      var dictionaryBox = box.GetExtension(DictionaryBox.Dictionary);
1003      return Activator.CreateInstance((Type)mapper.GetObject(box.TypeId), dictionaryBox.ValueIdsCount);
1004    }
1005    public override void FillFromBox(object obj, Box box, Mapper mapper) {
1006      var type = obj.GetType();
1007      var dictionaryBox = box.GetExtension(DictionaryBox.Dictionary);
1008      var comparerObj = mapper.GetObject(dictionaryBox.ComparerId);
1009      var comparer = comparerObj is Type ? Activator.CreateInstance((Type)comparerObj) : comparerObj;
1010
1011      var fieldInfo = type.GetField("comparer", BindingFlags.NonPublic | BindingFlags.Instance);
1012      fieldInfo.SetValue(obj, comparer);
1013
1014
1015      var addMethod = type.GetMethod("Add");
1016      for (int i = 0; i < dictionaryBox.KeyIdsCount; i++) {
1017        var key = mapper.GetObject(dictionaryBox.GetKeyIds(i));
1018        var value = mapper.GetObject(dictionaryBox.GetValueIds(i));
1019        addMethod.Invoke(obj, new[] { key, value });
1020      }
1021    }
1022  }
1023}
Note: See TracBrowser for help on using the repository browser.