18 using System.Collections.Generic;
24 namespace Deveel.Data.Serialization {
27 Encoding = Encoding.Unicode;
30 public Encoding Encoding {
get; set; }
34 throw new ArgumentNullException(
"stream");
36 throw new ArgumentException(
"The input stream cannot be read.",
"stream");
38 var reader =
new BinaryReader(stream, Encoding);
39 return Deserialize(reader, graphType);
42 public object Deserialize(BinaryReader reader, Type graphType) {
44 throw new ArgumentNullException(
"reader");
45 if (graphType == null)
46 throw new ArgumentNullException(
"graphType");
49 throw new ArgumentException(String.Format(
"The type '{0}' is not marked as serializable.", graphType));
52 return CustomDeserialize(reader, graphType);
54 return DeserializeType(reader, graphType);
58 var ctor = GetDefaultConstructor(graphType);
60 throw new NotSupportedException(String.Format(
"The type '{0}' does not specify any default empty constructor.", graphType));
62 var fields = graphType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
64 var properties = graphType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
67 var members =
new List<MemberInfo>();
68 members.AddRange(fields.Cast<MemberInfo>());
69 members.AddRange(properties.Cast<MemberInfo>());
71 var values =
new Dictionary<string, object>();
72 ReadValues(reader, Encoding, values);
74 var obj = ctor.Invoke(
new object[0]);
76 foreach (var member
in members) {
77 var memberName = member.Name;
80 if (values.TryGetValue(memberName, out value)) {
83 if (member is PropertyInfo) {
84 var
property = (PropertyInfo) member;
85 property.SetValue(obj, value, null);
86 }
else if (member is FieldInfo) {
87 var field = (FieldInfo) member;
88 field.SetValue(obj, value);
97 var ctors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
98 foreach (var ctor
in ctors) {
99 if (ctor.GetParameters().Length == 0)
107 var ctor = GetSpecialConstructor(graphType);
109 throw new NotSupportedException(String.Format(
"The type '{0}' has not the special serialization constructor",
112 var values =
new Dictionary<string, object>();
113 ReadValues(reader, Encoding, values);
115 var graph =
new ObjectData(graphType, values);
116 return ctor.Invoke(
new object[] {graph});
119 private static void ReadValues(BinaryReader reader, Encoding encoding, IDictionary<string, object> values) {
120 int count = reader.ReadInt32();
122 for (
int i = 0; i < count; i++) {
123 var keyLen = reader.ReadInt32();
124 var keyChars = reader.ReadChars(keyLen);
125 var key =
new string(keyChars);
127 var value = ReadValue(reader, encoding);
133 private static object ReadValue(BinaryReader reader, Encoding encoding) {
134 var typeCode = reader.ReadByte();
135 var nullCheck = reader.ReadBoolean();
140 if (typeCode == BooleanType)
141 return reader.ReadBoolean();
142 if (typeCode == ByteType)
143 return reader.ReadByte();
144 if (typeCode == Int16Type)
145 return reader.ReadInt16();
146 if (typeCode == Int32Type)
147 return reader.ReadInt32();
148 if (typeCode == Int64Type)
149 return reader.ReadInt64();
150 if (typeCode == SingleType)
151 return reader.ReadSingle();
152 if (typeCode == DoubleType)
153 return reader.ReadDouble();
154 if (typeCode == StringType)
155 return reader.ReadString();
156 if (typeCode == ObjectType)
157 return ReadObject(reader, encoding);
158 if (typeCode == ArrayType)
159 return ReadArray(reader, encoding);
161 throw new NotSupportedException(
"Invalid type code in serialization graph");
164 private static Type
ReadType(BinaryReader reader) {
165 var typeString = reader.ReadString();
166 return Type.GetType(typeString,
true);
169 private static object ReadObject(BinaryReader reader, Encoding encoding) {
170 var objType = ReadType(reader);
178 private static Array
ReadArray(BinaryReader reader, Encoding encoding) {
179 var objType = ReadType(reader);
180 var arrayLength = reader.ReadInt32();
181 var array = Array.CreateInstance(objType, arrayLength);
182 for (
int i = 0; i < arrayLength; i++) {
183 array.SetValue(ReadValue(reader, encoding), i);
190 var ctors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
191 foreach (var ctor
in ctors) {
192 var paramTypes = ctor.GetParameters().Select(x => x.ParameterType).ToArray();
193 if (paramTypes.Length == 1 && paramTypes[0] == typeof(
ObjectData))
202 throw new ArgumentNullException(
"stream");
204 if (!stream.CanWrite)
205 throw new ArgumentException(
"The serialization stream is not writeable.");
207 var writer =
new BinaryWriter(stream, Encoding);
208 Serialize(writer, obj);
211 public void Serialize(BinaryWriter writer,
object obj) {
213 throw new ArgumentNullException(
"writer");
215 throw new ArgumentNullException(
"obj");
217 var objType = obj.GetType();
220 throw new ArgumentException(String.Format(
"The type '{0} is not serializable", objType.FullName));
227 GetObjectValues(objType, obj, graph);
230 SerializeGraph(writer, Encoding, graph);
234 var fields = objType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
236 var properties = objType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
239 var members =
new List<MemberInfo>();
240 members.AddRange(fields.Cast<MemberInfo>());
241 members.AddRange(properties.Cast<MemberInfo>());
243 foreach (var member
in members) {
244 var memberName = member.Name;
248 if (member is FieldInfo) {
249 value = ((FieldInfo) member).GetValue(obj);
250 memberType = ((FieldInfo) member).FieldType;
251 }
else if (member is PropertyInfo) {
252 value = ((PropertyInfo) member).GetValue(obj, null);
253 memberType = ((PropertyInfo) member).PropertyType;
255 throw new NotSupportedException();
258 graph.SetValue(memberName, memberType, value);
263 var values = graph.
Values.ToDictionary(x => x.Key, x => x.Value);
264 var count = values.Count;
268 foreach (var pair
in values) {
270 var keyLength = key.Length;
272 writer.Write(keyLength);
273 writer.Write(key.ToCharArray());
275 SerializeValue(writer, encoding, pair.Value.Key, pair.Value.Value);
279 private const byte BooleanType = 1;
280 private const byte ByteType = 2;
281 private const byte Int16Type = 3;
282 private const byte Int32Type = 4;
283 private const byte Int64Type = 5;
284 private const byte SingleType = 6;
285 private const byte DoubleType = 7;
286 private const byte StringType = 8;
287 private const byte ObjectType = 15;
288 private const byte ArrayType = 20;
294 if (type.IsPrimitive) {
295 if (type == typeof(
bool))
297 if (type == typeof(byte))
299 if (type == typeof(
short))
301 if (type == typeof(
int))
303 if (type == typeof(
long))
305 if (type == typeof(
float))
307 if (type == typeof(
double))
311 if (type == typeof (
string))
320 private static void SerializeValue(BinaryWriter writer, Encoding encoding, Type type,
object value) {
321 var typeCode = GetTypeCode(type);
322 if (typeCode == null)
323 throw new NotSupportedException(String.Format(
"The type '{0}' is not supported.", type));
325 var nullCheck = value == null;
327 writer.Write(typeCode.Value);
328 writer.Write(nullCheck);
333 if (typeCode == ArrayType) {
334 var typeString = type.GetElementType().FullName;
335 writer.Write(typeString);
337 var array = (Array) value;
338 var arrayLength = array.Length;
339 var arrayType = type.GetElementType();
341 writer.Write(arrayLength);
343 for (
int i = 0; i < arrayLength; i++) {
344 var element = array.GetValue(i);
345 SerializeValue(writer, encoding, arrayType, element);
347 }
else if (typeCode == ObjectType) {
348 var realType = value.GetType();
349 writer.Write(realType.FullName);
353 }
else if (typeCode == BooleanType) {
354 writer.Write((
bool) value);
355 }
else if (typeCode == ByteType) {
356 writer.Write((byte) value);
357 }
else if (typeCode == Int16Type) {
358 writer.Write((
short) value);
359 }
else if (typeCode == Int32Type) {
360 writer.Write((
int) value);
361 }
else if (typeCode == Int64Type) {
362 writer.Write((
long) value);
363 }
else if (typeCode == SingleType) {
364 writer.Write((
float) value);
365 }
else if (typeCode == DoubleType) {
366 writer.Write((
double) value);
367 }
else if (typeCode == StringType) {
368 writer.Write((
string) value);
IEnumerable< KeyValuePair< string, KeyValuePair< Type, object > > > Values
static void ReadValues(BinaryReader reader, Encoding encoding, IDictionary< string, object > values)
static Array ReadArray(BinaryReader reader, Encoding encoding)
object Deserialize(Stream stream, Type graphType)
void Serialize(Stream stream, object obj)
object CustomDeserialize(BinaryReader reader, Type graphType)
ConstructorInfo GetDefaultConstructor(Type type)
ConstructorInfo GetSpecialConstructor(Type type)
static void SerializeValue(BinaryWriter writer, Encoding encoding, Type type, object value)
void Serialize(BinaryWriter writer, object obj)
static object ReadObject(BinaryReader reader, Encoding encoding)
object Deserialize(BinaryReader reader, Type graphType)
static Type ReadType(BinaryReader reader)
static object ReadValue(BinaryReader reader, Encoding encoding)
static void GetObjectValues(Type objType, object obj, SerializeData graph)
object DeserializeType(BinaryReader reader, Type graphType)
static byte GetTypeCode(Type type)
static void SerializeGraph(BinaryWriter writer, Encoding encoding, SerializeData graph)