private static object ReadValueType(Type valueType, ExtendedBinaryReader br, bool noAlign = false) { if (!noAlign) { br.AlignStream(); } if (valueType == typeof(string)) { return(br.ReadAlignedString()); } else if (valueType == typeof(Int32)) { return(br.ReadInt32()); } else if (valueType == typeof(UInt32)) { return(br.ReadUInt32()); } else if (valueType == typeof(Int64)) { return(br.ReadInt64()); } else if (valueType == typeof(UInt64)) { return(br.ReadUInt64()); } else if (valueType == typeof(Int16)) { return(br.ReadInt16()); } else if (valueType == typeof(UInt16)) { return(br.ReadUInt16()); } else if (valueType == typeof(Byte)) { return(br.ReadByte()); } else if (valueType == typeof(SByte)) { return(br.ReadSByte()); } else if (valueType == typeof(Boolean)) { return(br.ReadBoolean()); } else if (valueType == typeof(Double)) { return(br.ReadDouble()); } else if (valueType == typeof(Single)) { return(br.ReadSingle()); } else { throw new ArgumentException($"{valueType} is not a value type"); } }
private Array ReadArray(Type elementType, ExtendedBinaryReader br) { int size = br.ReadInt32(); if (size > 0x40000) { throw new IOException("Size exceeds limit : " + size); } var valueArray = Array.CreateInstance(elementType, size); if (elementType == typeof(string)) { for (int i = 0; i < size; i++) { valueArray.SetValue(br.ReadAlignedString(), i); } } else { for (int i = 0; i < size; i++) { valueArray.SetValue(Deserialize(elementType, br), i); } } return(valueArray); }
public object Deserialize(Type classType, ExtendedBinaryReader br, object obj = null) { if (!Attribute.IsDefined(classType, typeof(UnitySerializableAttribute))) { throw new UnitySerializationException("Not deserializable type : " + classType.FullName); } if (obj == null) { obj = Activator.CreateInstance(classType); } // Deserialize base type first because Type.GetFields() returns base fields last if (Attribute.IsDefined(classType.BaseType, typeof(UnitySerializableAttribute))) { Deserialize(classType.BaseType, br, obj); } var fieldArray = classType.GetFields(); foreach (var field in fieldArray) { if (!field.DeclaringType.Equals(classType)) { continue; } if (field.IsLiteral || field.IsInitOnly) { continue; } Type fieldType = field.FieldType; if (Attribute.IsDefined(field, typeof(UnityMinVersionAttribute))) { var minAttrib = Attribute.GetCustomAttribute(field, typeof(UnityMinVersionAttribute)) as UnityMinVersionAttribute; if (minAttrib.version > version) { field.SetValue(obj, GetDefault(fieldType)); continue; } } if (Attribute.IsDefined(field, typeof(UnityMaxVersionAttribute))) { var maxAttrib = Attribute.GetCustomAttribute(field, typeof(UnityMaxVersionAttribute)) as UnityMaxVersionAttribute; if (maxAttrib.version < version) { field.SetValue(obj, GetDefault(fieldType)); continue; } } object value = null; bool doNotAlign = Attribute.IsDefined(field, typeof(UnityDoNotAlignAttribute)); if (!doNotAlign) { br.AlignStream(); } if (fieldType.IsEnum) { var enumType = Enum.GetUnderlyingType(fieldType); value = ReadValueType(enumType, br); } else if (fieldType.IsValueType) { value = ReadValueType(fieldType, br); } else if (fieldType.IsArray && fieldType.GetElementType().IsValueType) // Value type array { value = ReadValueArray(fieldType.GetElementType(), br); } else if (fieldType == typeof(string)) { value = br.ReadAlignedString(); } else if (fieldType.IsClass || Attribute.IsDefined(fieldType, typeof(UnitySerializableAttribute))) { if (fieldType.IsArray) { var elementType = fieldType.GetElementType(); value = ReadArray(elementType, br); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(List <>)) { var elementType = fieldType.GetGenericArguments()[0]; object array; if (elementType.IsValueType) { array = ReadValueArray(elementType, br); } else { array = ReadArray(elementType, br); } value = Activator.CreateInstance(fieldType, (IEnumerable)array); } else { value = Deserialize(fieldType, br); } } else { throw new IOException("Failed to deserialize, unknown type : " + fieldType.ToString()); } field.SetValue(obj, value); } return(obj); }