Skip to content
This repository has been archived by the owner on Nov 14, 2022. It is now read-only.

Commit

Permalink
Merge pull request #22 from lukasz-pyrzyk/preparationForStream
Browse files Browse the repository at this point in the history
Preparation for stream
  • Loading branch information
YPermitin authored Jul 8, 2017
2 parents 731915d + 7206b6e commit ab6fd41
Show file tree
Hide file tree
Showing 41 changed files with 357 additions and 215 deletions.
131 changes: 44 additions & 87 deletions src/BinaryFormatter/BinaryConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,124 +5,80 @@
using BinaryFormatter.TypeConverter;
using BinaryFormatter.Types;
using System.Collections;
using System.IO;

namespace BinaryFormatter
{
public class BinaryConverter
{
private static readonly List<string> excludedDlls = new List<string> { "CoreLib", "mscorlib" };
private static readonly IDictionary<Type, BaseTypeConverter> _converters = new Dictionary<Type, BaseTypeConverter>
{
[typeof(byte)] = new ByteConverter(),
[typeof(sbyte)] = new SByteConverter(),
[typeof(char)] = new CharConverter(),
[typeof(short)] = new ShortConverter(),
[typeof(ushort)] = new UShortConverter(),
[typeof(int)] = new IntConverter(),
[typeof(uint)] = new UIntConverter(),
[typeof(long)] = new LongConverter(),
[typeof(ulong)] = new ULongConverter(),
[typeof(float)] = new FloatConverter(),
[typeof(double)] = new DoubleConverter(),
[typeof(bool)] = new BoolConverter(),
[typeof(decimal)] = new DecimalConverter(),
[typeof(string)] = new StringConverter(),
[typeof(DateTime)] = new DatetimeConverter(),
[typeof(byte[])] = new ByteArrayConverter(),
[typeof(IEnumerable)] = new IEnumerableConverter()
};
private static readonly ConvertersSelector _selector = new ConvertersSelector();

public byte[] Serialize(object obj)
{
Type t = obj.GetType();
var stream = new MemoryStream();
Serialize(obj, stream);
return stream.ToArray();
}

public void Serialize(object obj, Stream stream)
{
if (obj == null) return;

BaseTypeConverter converter;
if (_converters.TryGetValue(t, out converter))
BaseTypeConverter converter = _selector.SelectConverter(obj);
if (converter != null)
{
return converter.Serialize(obj);
} else if (obj is IEnumerable)
converter.Serialize(obj, stream);
}
else
{
if (_converters.TryGetValue(typeof(IEnumerable), out converter))
{
return converter.Serialize(obj);
}
SerializePropertiesToStream(obj, stream);
}

return SerializeProperties(obj);
}

private byte[] SerializeProperties(object obj)
private void SerializePropertiesToStream(object obj, Stream stream)
{
Type t = obj.GetType();
ICollection<PropertyInfo> properties = t.GetTypeInfo().DeclaredProperties.ToArray();

List<byte> serializedObject = new List<byte>();
foreach (PropertyInfo property in properties)
{
object prop = property.GetValue(obj);
byte[] elementBytes = GetBytesFromProperty(prop);
serializedObject.AddRange(elementBytes);
Serialize(prop, stream);
}

return serializedObject.ToArray();
}

private byte[] GetBytesFromProperty(object element)
public T Deserialize<T>(byte[] stream)
{
if (element == null) return new byte[0];
Type type = typeof(T);

Type t = element.GetType();
BaseTypeConverter converter;
if (_converters.ContainsKey(t))
{
converter = _converters[t];
return converter.Serialize(element);
} else if (element is IEnumerable)
BaseTypeConverter converter = _selector.SelectConverter(type);
if (converter == null)
{
if (_converters.TryGetValue(typeof(IEnumerable), out converter))
{
return converter.Serialize(element);
}
}
T instance = (T)Activator.CreateInstance(type);

return SerializeProperties(element);
}
int offset = 0;
DeserializeObject(stream, ref instance, ref offset);

public T Deserialize<T>(byte[] stream)
{
Type type = typeof(T);

bool isEnumerableType = type.GetTypeInfo().ImplementedInterfaces
.Where(t => t == typeof(IEnumerable)).Count() > 0;
return instance;
}

BaseTypeConverter converter;
if (_converters.TryGetValue(type, out converter))
if (converter is IEnumerableConverter)
{
return (T)converter.DeserializeToObject(stream);
} else if (isEnumerableType)
{
if (_converters.TryGetValue(typeof(IEnumerable), out converter))
{
var prepearedData = converter.DeserializeToObject(stream) as IEnumerable;

var listType = typeof(List<>);
var genericArgs = type.GenericTypeArguments;
var concreteType = listType.MakeGenericType(genericArgs);
var data = Activator.CreateInstance(concreteType);
foreach (var item in prepearedData)
{
((IList)data).Add(item);
}
return (T)data;
var prepearedData = converter.DeserializeToObject(stream) as IEnumerable;

var listType = typeof(List<>);
var genericArgs = type.GenericTypeArguments;
var concreteType = listType.MakeGenericType(genericArgs);
var data = Activator.CreateInstance(concreteType);
foreach (var item in prepearedData)
{
((IList)data).Add(item);
}
return (T)data;
}

T instance = (T)Activator.CreateInstance(type);

int offset = 0;
DeserializeObject(stream, ref instance, ref offset);

return instance;
return (T)converter.DeserializeToObject(stream);
}

private void DeserializeObject<T>(byte[] stream, ref T instance, ref int offset)
Expand All @@ -149,23 +105,24 @@ private void DeserializeProperty<T>(PropertyInfo property, ref T instance, byte[
TypeInfo instanceTypeInfo = instanceType.GetTypeInfo();
SerializedType type = (SerializedType)BitConverter.ToInt16(stream, offset);
offset += sizeof(short);
BaseTypeConverter converter = _converters.First(x => x.Value.Type == type).Value;

BaseTypeConverter converter = _selector.ForSerializedType(type);
object data;
if (type == SerializedType.IEnumerable)
{
var prepearedData = converter.DeserializeToObject(stream, ref offset) as IEnumerable;

var prop = property;
var listType = typeof(List<>);
var genericArgs = prop.PropertyType.GenericTypeArguments;
var genericArgs = prop.PropertyType.GenericTypeArguments;
var concreteType = listType.MakeGenericType(genericArgs);
data = Activator.CreateInstance(concreteType);
foreach (var item in prepearedData)
{
((IList)data).Add(item);
}
} else
}
else
{
data = converter.DeserializeToObject(stream, ref offset);
}
Expand Down
66 changes: 66 additions & 0 deletions src/BinaryFormatter/ConvertersSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BinaryFormatter.TypeConverter;
using BinaryFormatter.Types;

namespace BinaryFormatter
{
internal class ConvertersSelector
{
private static readonly Dictionary<Type, BaseTypeConverter> _converters = new Dictionary<Type, BaseTypeConverter>
{
[typeof(byte)] = new ByteConverter(),
[typeof(sbyte)] = new SByteConverter(),
[typeof(char)] = new CharConverter(),
[typeof(short)] = new ShortConverter(),
[typeof(ushort)] = new UShortConverter(),
[typeof(int)] = new IntConverter(),
[typeof(uint)] = new UIntConverter(),
[typeof(long)] = new LongConverter(),
[typeof(ulong)] = new ULongConverter(),
[typeof(float)] = new FloatConverter(),
[typeof(double)] = new DoubleConverter(),
[typeof(bool)] = new BoolConverter(),
[typeof(decimal)] = new DecimalConverter(),
[typeof(string)] = new StringConverter(),
[typeof(DateTime)] = new DatetimeConverter(),
[typeof(byte[])] = new ByteArrayConverter(),
[typeof(IEnumerable)] = new IEnumerableConverter()
};

public BaseTypeConverter SelectConverter(object obj)
{
if(obj == null) return null;
Type type = obj.GetType();
return SelectConverter(type);
}

public BaseTypeConverter SelectConverter(Type type)
{
BaseTypeConverter converter;
if (_converters.TryGetValue(type, out converter))
{
return converter;
}

bool isEnumerableType = type.GetTypeInfo().ImplementedInterfaces.Any(t => t == typeof(IEnumerable));
if (isEnumerableType)
{
if (_converters.TryGetValue(typeof(IEnumerable), out converter))
{
return converter;
}
}

return null;
}

public BaseTypeConverter ForSerializedType(SerializedType type)
{
return _converters.First(x => x.Value.Type == type).Value;
}
}
}
23 changes: 9 additions & 14 deletions src/BinaryFormatter/TypeConverter/BaseTypeConverter.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
using System;
using System.IO;
using BinaryFormatter.Types;
using BinaryFormatter.Utils;

namespace BinaryFormatter.TypeConverter
{
internal abstract class BaseTypeConverter<T> : BaseTypeConverter
{
public byte[] Serialize(T obj)
public void Serialize(T obj, Stream stream)
{
if (obj == null) throw new ArgumentNullException(nameof(obj));

byte[] objectBytes = ProcessSerialize(obj);
byte[] objectType = BitConverter.GetBytes((ushort)Type);
stream.Write(objectType);

byte[] final = new byte[objectType.Length + objectBytes.Length];

int offset = 0;
Array.Copy(objectType, 0, final, offset, objectType.Length);
offset += objectType.Length;
Array.Copy(objectBytes, 0, final, offset, objectBytes.Length);

return final;
WriteObjectToStream(obj, stream);
}

public override byte[] Serialize(object obj)
public override void Serialize(object obj, Stream stream)
{
if (obj == null) throw new ArgumentNullException(nameof(obj));

return Serialize((T)obj);
Serialize((T)obj, stream);
}

public T Deserialize(byte[] stream)
Expand All @@ -53,7 +48,7 @@ public override object DeserializeToObject(byte[] stream, ref int offset)
}

protected abstract int GetTypeSize();
protected abstract byte[] ProcessSerialize(T obj);
protected abstract void WriteObjectToStream(T obj, Stream stream);
protected abstract T ProcessDeserialize(byte[] stream, ref int offset);

protected virtual SerializedType GetPackageType(byte[] stream, ref int offset)
Expand All @@ -66,7 +61,7 @@ protected virtual SerializedType GetPackageType(byte[] stream, ref int offset)

internal abstract class BaseTypeConverter
{
public abstract byte[] Serialize(object obj);
public abstract void Serialize(object obj, Stream stream);
public abstract object DeserializeToObject(byte[] stream);
public abstract object DeserializeToObject(byte[] stream, ref int offset);
public abstract SerializedType Type { get; }
Expand Down
7 changes: 5 additions & 2 deletions src/BinaryFormatter/TypeConverter/BoolConverter.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System;
using System.IO;
using BinaryFormatter.Types;
using BinaryFormatter.Utils;

namespace BinaryFormatter.TypeConverter
{
internal class BoolConverter : BaseTypeConverter<bool>
{
protected override byte[] ProcessSerialize(bool obj)
protected override void WriteObjectToStream(bool obj, Stream stream)
{
return BitConverter.GetBytes(obj);
byte[] data = BitConverter.GetBytes(obj);
stream.Write(data);
}

protected override bool ProcessDeserialize(byte[] stream, ref int offset)
Expand Down
11 changes: 5 additions & 6 deletions src/BinaryFormatter/TypeConverter/ByteArrayConverter.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
using System;
using System.IO;
using BinaryFormatter.Types;
using BinaryFormatter.Utils;

namespace BinaryFormatter.TypeConverter
{
internal class ByteArrayConverter : BaseTypeConverter<byte[]>
{
private int Size { get; set; }

protected override byte[] ProcessSerialize(byte[] obj)
protected override void WriteObjectToStream(byte[] obj, Stream stream)
{
Size = obj.Length;
byte[] lengthBytes = BitConverter.GetBytes(Size);

byte[] serializedStringWithSize = new byte[sizeof(int) + Size];
Array.Copy(lengthBytes, 0, serializedStringWithSize, 0, lengthBytes.Length);
Array.Copy(obj, 0, serializedStringWithSize, lengthBytes.Length, obj.Length);

return serializedStringWithSize;
stream.Write(lengthBytes);
stream.Write(obj);
}

protected override byte[] ProcessDeserialize(byte[] stream, ref int offset)
Expand Down
7 changes: 5 additions & 2 deletions src/BinaryFormatter/TypeConverter/ByteConverter.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System;
using System.IO;
using BinaryFormatter.Types;
using BinaryFormatter.Utils;

namespace BinaryFormatter.TypeConverter
{
internal class ByteConverter : BaseTypeConverter<byte>
{
protected override byte[] ProcessSerialize(byte obj)
protected override void WriteObjectToStream(byte obj, Stream stream)
{
return BitConverter.GetBytes(obj);
byte[] data = BitConverter.GetBytes(obj);
stream.Write(data);
}

protected override byte ProcessDeserialize(byte[] stream, ref int offset)
Expand Down
Loading

0 comments on commit ab6fd41

Please sign in to comment.