forked from karlseguin/Metsys.Little
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Deserializer.cs
113 lines (105 loc) · 4.01 KB
/
Deserializer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace Metsys.Little
{
public class Deserializer
{
private static readonly LittleConfiguration _configuration = LittleConfiguration.Instance;
private static readonly IDictionary<Type, Func<Deserializer, object>> _readerLookup = new Dictionary<Type, Func<Deserializer, object>>
{
{typeof (bool), d => d._reader.ReadBoolean()},
{typeof (int), d => d._reader.ReadInt32()},
{typeof (short), d => d._reader.ReadInt16()},
{typeof (long), d => d._reader.ReadInt64()},
{typeof (float), d => d._reader.ReadSingle()},
{typeof (double), d => d._reader.ReadDouble()},
{typeof (decimal), d => d._reader.ReadDecimal()},
{typeof (byte), d => d._reader.ReadByte()},
{typeof (string), d => d._reader.ReadString()},
{typeof (char), d => d._reader.ReadChar()},
{typeof (DateTime), d => d.ReadDateTime()},
{typeof(Guid), d => new Guid(d._reader.ReadBytes(16))},
};
private readonly BinaryReader _reader;
private Deserializer(BinaryReader reader)
{
_reader = reader;
}
public static T Deserialize<T>(byte[] objectData) where T : class
{
using (var ms = new MemoryStream())
{
ms.Write(objectData, 0, objectData.Length);
ms.Position = 0;
return Deserialize<T>(new BinaryReader(ms));
}
}
public static T Deserialize<T>(BinaryReader stream)
{
return new Deserializer(stream).Read<T>();
}
private T Read<T>()
{
return (T) DeserializeValue(typeof (T), null);
}
private object DeserializeValue(Type type, object container)
{
Func<Deserializer, object> r;
if (_readerLookup.TryGetValue(type, out r))
{
return r(this);
}
if (typeof (IEnumerable).IsAssignableFrom(type))
{
return ReadList(type, container);
}
return ReadObject(type);
}
private object ReadList(Type listType, object existingContainer)
{
var totalItems = _reader.ReadInt32();
var count = 0;
var itemType = ListHelper.GetListItemType(listType);
var wrapper = BaseWrapper.Create(listType, itemType, existingContainer);
while (count++ < totalItems)
{
var value = DeserializeValue(itemType, null);
wrapper.Add(value);
}
return wrapper.Collection;
}
private DateTime ReadDateTime()
{
if (_configuration.DateTimeMode == DateTimeMode.Detailed)
{
return DateTime.FromBinary(_reader.ReadInt64());
}
return Helper.Epoch.AddSeconds(_reader.ReadInt32());
}
private object ReadObject(Type type)
{
var helper = TypeHelper.GetHelperForType(type);
var instance = helper.Create();
foreach (var property in helper.Properties)
{
object container = null;
if (property.Setter == null)
{
container = property.Getter(instance);
}
var value = property.Nullable && IsNull() ? null : DeserializeValue(property.Type, container);
if (container == null)
{
property.Setter(instance, value);
}
}
return instance;
}
private bool IsNull()
{
return _reader.ReadByte() == 0;
}
}
}