Example #1
0
        public static object Deserialize(
            BinaryReader reader, Type type,
            bool isNullableIfReferenceType, bool areElementsNullableIfReferenceType
            )
        {
            var nullableUnderlyingType = Nullable.GetUnderlyingType(type);

            if ((nullableUnderlyingType == null) && isNullableIfReferenceType && type.IsClass)
            {
                nullableUnderlyingType = type;
            }

            if (nullableUnderlyingType != null)
            {
                var objHasValue = reader.ReadBoolean();
                return(objHasValue
                    ? Deserialize(
                           reader, nullableUnderlyingType, isNullableIfReferenceType: false,
                           areElementsNullableIfReferenceType: areElementsNullableIfReferenceType
                           ) : null);
            }
            else if (type == typeof(bool))
            {
                return(reader.ReadBoolean());
            }
            else if (type == typeof(sbyte))
            {
                return(reader.ReadSByte());
            }
            else if (type == typeof(byte))
            {
                return(reader.ReadByte());
            }
            else if (type == typeof(ushort))
            {
                return(reader.ReadUInt16());
            }
            else if (type == typeof(short))
            {
                return(reader.ReadInt16());
            }
            else if (type == typeof(uint))
            {
                return(reader.ReadUInt32());
            }
            else if (type == typeof(int))
            {
                return(reader.ReadInt32());
            }
            else if (type == typeof(ulong))
            {
                return(reader.ReadUInt64());
            }
            else if (type == typeof(long))
            {
                return(reader.ReadInt64());
            }
            else if (type == typeof(float))
            {
                return(reader.ReadSingle());
            }
            else if (type == typeof(double))
            {
                return(reader.ReadDouble());
            }
            else if (type == typeof(decimal))
            {
                return(reader.ReadDecimal());
            }
            else if (type == typeof(char))
            {
                return(reader.ReadChar());
            }
            else if (type == typeof(string))
            {
                return(reader.ReadString());
            }
            else if (type == typeof(float2))
            {
                var result = new float2();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(float3))
            {
                var result = new float3();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(float4))
            {
                var result = new float4();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector2))
            {
                var result = new Vector2();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector3))
            {
                var result = new Vector3();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector4))
            {
                var result = new Vector4();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (typeof(INetworkSerializable).IsAssignableFrom(type))
            {
                var result = Activator.CreateInstance(type);
                ((INetworkSerializable)result).Deserialize(reader);

                return(result);
            }
            else if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                if (typeof(Array).IsAssignableFrom(type))
                {
                    var elementType  = type.GetElementType();
                    var elementCount = reader.ReadUInt32();
                    var array        = Array.CreateInstance(elementType, elementCount);

                    for (var i = 0; i < elementCount; i++)
                    {
                        var element = Deserialize(
                            reader, elementType, isNullableIfReferenceType: areElementsNullableIfReferenceType,
                            areElementsNullableIfReferenceType: false
                            );
                        array.SetValue(element, i);
                    }

                    return(array);
                }
                else if (typeof(IList).IsAssignableFrom(type))
                {
                    var list         = (IList)Activator.CreateInstance(type);
                    var elementType  = type.GenericTypeArguments[0];
                    var elementCount = reader.ReadUInt32();

                    for (var i = 0; i < elementCount; i++)
                    {
                        var element = Deserialize(
                            reader, elementType, isNullableIfReferenceType: areElementsNullableIfReferenceType,
                            areElementsNullableIfReferenceType: false
                            );
                        list.Add(element);
                    }

                    return(list);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                if (type.IsEnum)
                {
                    var smallestTypeToHoldEnumValues = GetSmallestUIntTypeToHoldEnumValues(type);
                    var enumValueAsInt = Deserialize(
                        reader, smallestTypeToHoldEnumValues, isNullableIfReferenceType: false,
                        areElementsNullableIfReferenceType: false
                        );

                    return(Enum.ToObject(type, enumValueAsInt));
                }
                else if (type.IsClass || type.IsValueType)
                {
                    var result = Activator.CreateInstance(type);

                    var objFields = NetLib.GetFieldInfosToSerialize(type);
                    foreach (var objField in objFields)
                    {
                        var fieldValue = Deserialize(
                            reader, objField.FieldType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                        objField.SetValue(result, fieldValue);
                    }

                    var objProperties = NetLib.GetPropertyInfosToSerialize(type);
                    foreach (var objProperty in objProperties)
                    {
                        if (!objProperty.CanRead || !objProperty.CanWrite)
                        {
                            continue;
                        }

                        var propertyValue = Deserialize(
                            reader, objProperty.PropertyType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                        objProperty.SetValue(result, propertyValue);
                    }

                    return(result);
                }
                else
                {
                    throw new NotImplementedException($"Cannot deserialize type: {type.AssemblyQualifiedName}");
                }
            }
        }
Example #2
0
        public static void SerializeObject(
            BinaryWriter writer, object obj, Type overrideType, bool isNullableIfReferenceType,
            bool areElementsNullableIfReferenceType
            )
        {
            Assert.IsTrue(!isNullableIfReferenceType || (overrideType != null));

            var objType = overrideType ?? obj?.GetType();

            Assert.IsNotNull(objType);
            Assert.IsTrue((obj != null) || !objType.IsClass || isNullableIfReferenceType);

            var nullableUnderlyingType = Nullable.GetUnderlyingType(objType);

            if ((nullableUnderlyingType == null) && isNullableIfReferenceType && objType.IsClass)
            {
                nullableUnderlyingType = objType;
            }

            if (nullableUnderlyingType != null)
            {
                writer.Write(obj != null);

                if (obj != null)
                {
                    objType = nullableUnderlyingType;
                }
                else
                {
                    return;
                }
            }

            if (objType == typeof(bool))
            {
                writer.Write((bool)obj);
            }
            else if (objType == typeof(sbyte))
            {
                writer.Write((sbyte)obj);
            }
            else if (objType == typeof(byte))
            {
                writer.Write((byte)obj);
            }
            else if (objType == typeof(ushort))
            {
                writer.Write((ushort)obj);
            }
            else if (objType == typeof(short))
            {
                writer.Write((short)obj);
            }
            else if (objType == typeof(uint))
            {
                writer.Write((uint)obj);
            }
            else if (objType == typeof(int))
            {
                writer.Write((int)obj);
            }
            else if (objType == typeof(ulong))
            {
                writer.Write((ulong)obj);
            }
            else if (objType == typeof(long))
            {
                writer.Write((long)obj);
            }
            else if (objType == typeof(float))
            {
                writer.Write((float)obj);
            }
            else if (objType == typeof(double))
            {
                writer.Write((double)obj);
            }
            else if (objType == typeof(decimal))
            {
                writer.Write((decimal)obj);
            }
            else if (objType == typeof(char))
            {
                writer.Write((char)obj);
            }
            else if (objType == typeof(string))
            {
                writer.Write((string)obj);
            }
            else if (objType == typeof(float2))
            {
                Serialize(writer, (float2)obj);
            }
            else if (objType == typeof(float3))
            {
                Serialize(writer, (float3)obj);
            }
            else if (objType == typeof(float4))
            {
                Serialize(writer, (float4)obj);
            }
            else if (objType == typeof(Vector2))
            {
                Serialize(writer, (Vector2)obj);
            }
            else if (objType == typeof(Vector3))
            {
                Serialize(writer, (Vector3)obj);
            }
            else if (objType == typeof(Vector4))
            {
                Serialize(writer, (Vector4)obj);
            }
            else if (typeof(INetworkSerializable).IsAssignableFrom(obj.GetType()))
            {
                ((INetworkSerializable)obj).Serialize(writer);
            }
            else if (typeof(ICollection).IsAssignableFrom(objType))
            {
                Type elementType;

                if (objType.IsArray)
                {
                    elementType = objType.GetElementType();
                }
                else if (objType.IsGenericType)
                {
                    elementType = objType.GetGenericArguments()[0];
                }
                else
                {
                    throw new NotImplementedException("Non-generic collections aren't supported.");
                }

                var collection = (ICollection)obj;
                writer.Write((uint)collection.Count);

                foreach (var element in collection)
                {
                    SerializeObject(
                        writer, element, overrideType: elementType,
                        isNullableIfReferenceType: areElementsNullableIfReferenceType,
                        areElementsNullableIfReferenceType: false
                        );
                }
            }
            else
            {
                if (objType.IsEnum)
                {
                    var smallestTypeToHoldEnumValues = GetSmallestUIntTypeToHoldEnumValues(objType);
                    var objToSerialize = Convert.ChangeType(obj, smallestTypeToHoldEnumValues);
                    SerializeObject(
                        writer, objToSerialize, overrideType: null, isNullableIfReferenceType: false,
                        areElementsNullableIfReferenceType: false
                        );
                }
                else if (objType.IsClass || objType.IsValueType)
                {
                    var objFields = NetLib.GetFieldInfosToSerialize(objType);
                    foreach (var objField in objFields)
                    {
                        SerializeObject(
                            writer, objField.GetValue(obj), objField.FieldType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                    }

                    var objProperties = NetLib.GetPropertyInfosToSerialize(objType);
                    foreach (var objProperty in objProperties)
                    {
                        if (!objProperty.CanRead || !objProperty.CanWrite)
                        {
                            continue;
                        }

                        SerializeObject(
                            writer, objProperty.GetValue(obj), objProperty.PropertyType,
                            isNullableIfReferenceType: false, areElementsNullableIfReferenceType: false
                            );
                    }
                }
                else
                {
                    throw new NotImplementedException($"Cannot serialize type: {objType.AssemblyQualifiedName}");
                }
            }
        }