/// <summary> /// Serialises the given <see cref="IList"/> to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// Uses <see cref="SerialiseObjectToWriter(object,BinaryWriter)"/> to serialise each of the <see cref="IList"/>s /// elements to the stream. /// </summary> /// <param name="obj"> /// The <see cref="IList"/> to serialise to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// </param> /// <param name="propertyInfo">The <see cref="PropertyInfo"/> holding the <see cref="IList"/>. </param> /// <param name="binaryWriter"> /// The <see cref="BinaryWriter"/> to whose underlying <see cref="MemoryStream"/> to serialise the given <see cref="PropertyInfo"/>. /// </param> /// <exception cref="NullReferenceException"> /// Thrown if the <see cref="IList"/> held in the given <see cref="PropertyInfo"/> is null, or if the <see cref="IList"/>s /// elements do not have a type. /// </exception> private void SerialiseListToWriter(object obj, PropertyInfo propertyInfo, BinaryWriter binaryWriter) { Type elementType = propertyInfo.PropertyType.GetGenericArguments()[0]; IList list = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType)); IEnumerable currentList = (IEnumerable)propertyInfo.GetValue(obj); foreach (object element in currentList) { list.Add(element); } binaryWriter.Write(list.Count); if (elementType.IsClass && !PacketConverterHelper.TypeIsPrimitive(elementType)) { foreach (object element in list) { SerialiseObjectToWriter(element, binaryWriter); } } else //Primitive type { foreach (object primitiveElement in list) { dynamic primitiveValue = primitiveElement; binaryWriter.Write(primitiveValue); } } }
/// <summary> /// Serialises the given <see cref="PropertyInfo"/> to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// </summary> /// <param name="obj">The <see cref="object"/> whose <see cref="PropertyInfo"/> value to serialise.</param> /// <param name="propertyInfo"> /// The <see cref="PropertyInfo"/> to serialise to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// </param> /// <param name="binaryWriter"> /// The <see cref="BinaryWriter"/> to whose underlying <see cref="MemoryStream"/> to serialise the given <see cref="PropertyInfo"/>. /// </param> private void SerialiseObjectToWriter(object obj, PropertyInfo propertyInfo, BinaryWriter binaryWriter) { Type propertyType = propertyInfo.PropertyType; dynamic propertyValue = propertyInfo.GetValue(obj); //We have an enum if (propertyType.IsEnum) { binaryWriter.Write(propertyValue.ToString()); } //We have an array else if (propertyType.IsArray) { SerialiseArrayToWriter(obj, propertyInfo, binaryWriter); } //We have a list else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List <>)) { SerialiseListToWriter(obj, propertyInfo, binaryWriter); } //We have a non-primitive type else if (!PacketConverterHelper.TypeIsPrimitive(propertyType)) { if (propertyValue != null) //Not null non-primitive type value { //There is a value to read from the network stream binaryWriter.Write((byte)ObjectState.NotNull); SerialiseObjectToWriter(propertyValue, binaryWriter); } else //Null non-primitive type value { //There isn't a value to read from the network stream binaryWriter.Write((byte)ObjectState.Null); } } //We have a primitive type else { if (propertyValue != null) //Not null primitive type value { //There is a value to read from the network stream binaryWriter.Write((byte)ObjectState.NotNull); //We write the value to the stream binaryWriter.Write(propertyValue); } else //Null primitive type value { //There isn't a value to read from the network stream binaryWriter.Write((byte)ObjectState.Null); } } }
/// <summary> /// Deserialises the given <see cref="Array"/> from the given <see cref="BinaryReader"/>s underlying /// <see cref="MemoryStream"/>. Uses <see cref="DeserialiseObjectFromReader(object,BinaryReader)"/> to serialise /// each of the <see cref="Array"/>s elements to the stream. /// </summary> /// <param name="obj"> /// The <see cref="Array"/> to deserialise from the given <see cref="BinaryReader"/>s underlying <see cref="MemoryStream"/>. /// </param> /// <param name="propertyInfo">The <see cref="PropertyInfo"/> holding the <see cref="Array"/>.</param> /// <param name="binaryReader"> /// The <see cref="BinaryReader"/> from whose underlying <see cref="MemoryStream"/> to deserialise the given /// <see cref="PropertyInfo"/>. /// </param> /// <exception cref="ArgumentNullException">Thrown if the <see cref="Array"/>s elements do not have a type.</exception> private Array ReadArrayFromStream(object obj, PropertyInfo propertyInfo, BinaryReader binaryReader) { int arraySize = binaryReader.ReadInt32(); Type elementType = propertyInfo.PropertyType.GetElementType(); Array array = Array.CreateInstance(elementType, arraySize); for (int i = 0; i < arraySize; ++i) { if (elementType.IsClass && !PacketConverterHelper.TypeIsPrimitive(elementType)) { array.SetValue(DeserialiseObjectFromReader(PacketConverterHelper.InstantiateObject(elementType), binaryReader), i); } else { array.SetValue(ReadPrimitiveFromStream(elementType, binaryReader), i); } } return(array); }
/// <summary> /// Deserialises the given <see cref="IList"/> from the given <see cref="BinaryReader"/>s underlying /// <see cref="MemoryStream"/>. Uses <see cref="DeserialiseObjectFromReader(object,BinaryReader)"/> to serialise /// each of the <see cref="IList"/>s elements to the stream. /// </summary> /// <param name="obj"> The <see cref="IList"/> to deserialise from the given <see cref="BinaryReader"/>s underlying /// <see cref="MemoryStream"/>. /// </param> /// <param name="propertyInfo">The <see cref="PropertyInfo"/> holding the <see cref="IList"/>.</param> /// <param name="binaryReader"> /// The <see cref="BinaryReader"/> from whose underlying <see cref="MemoryStream"/> to deserialise the given /// <see cref="PropertyInfo"/>. /// </param> /// <exception cref="NullReferenceException"> /// Thrown if the <see cref="IList"/> held in the <see cref="MemoryStream"/> is null, or if the <see cref="IList"/>s /// elements do not have a type. /// </exception> private IList ReadListFromStream(object obj, PropertyInfo propertyInfo, BinaryReader binaryReader) { int listSize = binaryReader.ReadInt32(); Type listType = propertyInfo.PropertyType.GetGenericArguments()[0]; IList list = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(listType)); for (int i = 0; i < listSize; ++i) { if (listType.IsClass && !PacketConverterHelper.TypeIsPrimitive(listType)) { list.Add(DeserialiseObjectFromReader(PacketConverterHelper.InstantiateObject(listType), binaryReader)); } else { list.Add(ReadPrimitiveFromStream(listType, binaryReader)); } } return(list); }
/// <summary> /// Deserialises the given <see cref="PropertyInfo"/> from the given <see cref="BinaryReader"/>s underlying /// <see cref="MemoryStream"/>. /// </summary> /// <param name="obj"> The <see cref="object"/> whose <see cref="PropertyInfo"/> value to deserialise.</param> /// <param name="propertyInfo"> /// The <see cref="PropertyInfo"/> to deserialise from the given <see cref="BinaryReader"/>s underlying /// <see cref="MemoryStream"/>. /// </param> /// <param name="binaryReader"> /// The <see cref="BinaryReader"/> from whose underlying <see cref="MemoryStream"/> to deserialise the given /// <see cref="PropertyInfo"/>. /// </param> /// <returns> /// The <see cref="object"/> deserialised from the <see cref="MemoryStream"/>. This can be null if the /// <see cref="ObjectState"/> is <see cref="ObjectState.Null"/>. /// </returns> private object DeserialiseObjectFromReader(object obj, PropertyInfo propertyInfo, BinaryReader binaryReader) { Type propertyType = propertyInfo.PropertyType; //We have an enumeration if (propertyType.IsEnum) { return(Enum.Parse(propertyType, binaryReader.ReadString())); } //We have an array if (propertyType.IsArray) { return(ReadArrayFromStream(obj, propertyInfo, binaryReader)); } //We have a generic list if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List <>)) { return(ReadListFromStream(obj, propertyInfo, binaryReader)); } ObjectState objectState = (ObjectState)binaryReader.ReadByte(); if (PacketConverterHelper.TypeIsPrimitive(propertyType)) //We have a primitive type { //If the primitive object is null we just return null, otherwise we deserialise from the stream return(objectState == ObjectState.NotNull ? ReadPrimitiveFromStream(propertyType, binaryReader) : null); } //We have a complex type //If the custom object is null we just return null, otherwise we deserialise from the stream return(objectState == ObjectState.NotNull ? DeserialiseObjectFromReader(PacketConverterHelper.InstantiateObject(propertyType), binaryReader) : null); }
/// <summary> /// Serialises the given <see cref="Array"/> to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// Uses <see cref="SerialiseObjectToWriter(object,BinaryWriter)"/> to serialise each of the <see cref="Array"/>s /// elements to the stream. /// </summary> /// <param name="obj"> /// The <see cref="Array"/> to serialise to the given <see cref="BinaryWriter"/>s underlying <see cref="MemoryStream"/>. /// </param> /// <param name="propertyInfo">The <see cref="PropertyInfo"/> holding the <see cref="Array"/>.</param> /// <param name="binaryWriter"> /// The <see cref="BinaryWriter"/> to whose underlying <see cref="MemoryStream"/> to serialise the given <see cref="PropertyInfo"/>. /// </param> /// <exception cref="NullReferenceException"> /// Thrown if the <see cref="Array"/> held in the given <see cref="PropertyInfo"/> is null, or if the <see cref="Array"/>s /// elements do not have a type. /// </exception> private void SerialiseArrayToWriter(object obj, PropertyInfo propertyInfo, BinaryWriter binaryWriter) { Type elementType = propertyInfo.PropertyType.GetElementType(); Array array = (Array)propertyInfo.GetValue(obj); binaryWriter.Write(array?.Length ?? 0); if (elementType.IsClass && !PacketConverterHelper.TypeIsPrimitive(elementType)) { foreach (object element in array) { SerialiseObjectToWriter(element, binaryWriter); } } else //Primitive element type { foreach (object primitiveElement in array) { dynamic primitiveValue = primitiveElement; binaryWriter.Write(primitiveValue); } } }