/// <summary> /// Read the specified type. /// </summary> /// <param name="type">Type.</param> public override object Read(Type type) { Type nullableType = null; object result = null; if (type == null || string.IsNullOrEmpty(m_Json)) { result = null; } else if (m_Json[m_Position] == 'n' && PeekString() == "null") { ReadString(); result = null; } else { if (Nullable.GetUnderlyingType(type) != null) { nullableType = type; type = Nullable.GetUnderlyingType(type); } bool isEnum = false; bool isSerializable = false; bool isGeneric = false; #if (UNITY_WSA || UNITY_WINRT) && !UNITY_EDITOR TypeInfo info = type.GetTypeInfo(); isEnum = info.IsEnum; isSerializable = info.IsSerializable; isGeneric = info.IsGenericType; #else isEnum = type.IsEnum; isSerializable = type.IsSerializable; isGeneric = type.IsGenericType; #endif if (type == typeof(UnityEngine.GameObject)) { // Skip object start m_Position++; m_IsFirstProperty = true; int layer = 0; bool isStatic = false; string tag = ""; string name = ""; UnityEngine.HideFlags hideFlags = UnityEngine.HideFlags.None; foreach (string property in Properties) { switch (property) { case "layer": layer = ReadProperty <int>(); break; case "isStatic": isStatic = ReadProperty <bool>(); break; case "tag": tag = ReadProperty <string>(); break; case "name": name = ReadProperty <string>(); break; case "hideFlags": hideFlags = ReadProperty <UnityEngine.HideFlags>(); break; } } UnityEngine.GameObject gameObject = new UnityEngine.GameObject(name); gameObject.layer = layer; gameObject.isStatic = isStatic; gameObject.tag = tag; gameObject.name = name; gameObject.hideFlags = hideFlags; // Skip comma m_Position++; ReadQoutedString(); // Skip colon and array start m_Position += 2; int length = GetArrayLength(); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } // Skip object start m_Position++; ReadQoutedString(); // Skip colon m_Position++; string typeFullName = ReadQoutedString(); Type componentType = Type.GetType(typeFullName); UnityEngine.Component component = gameObject.GetComponent(componentType); if (componentType != typeof(UnityEngine.Transform) && componentType.BaseType != typeof(UnityEngine.Transform)) { UnityEngine.Component newComponent = gameObject.AddComponent(componentType); if (newComponent != null) { component = newComponent; } } // Skip comma m_Position++; ReadQoutedString(); // Skip colon m_Position++; ReadInto(component); // Skip object end m_Position++; } // Skip comma and array end m_Position += 2; ReadQoutedString(); // Skip colon and array start m_Position += 2; length = GetArrayLength(); isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } ReadChild(gameObject); } result = gameObject; // Skip object end m_Position++; } else if (type == typeof(string)) { result = ReadQoutedString().UnEscapeStringJson(); } else if (isEnum) { result = Enum.Parse(type, ReadQoutedString().UnEscapeStringJson()); } else if (type == typeof(bool)) { result = bool.Parse(ReadString()); } else if (type == typeof(short) || type == typeof(int) || type == typeof(long) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong) || type == typeof(byte) || type == typeof(sbyte) || type == typeof(decimal) || type == typeof(double) || type == typeof(float)) { result = Convert.ChangeType(ReadString(), type); } else if (type.IsArray) { // Skip array start m_Position++; Type elementType = type.GetElementType(); int length = GetArrayLength(); Array array = Array.CreateInstance(elementType, length); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } array.SetValue(Read(elementType), i); } result = array; // Skip array end m_Position++; } else if (type == typeof(DictionaryEntry)) { // Skip object start m_Position++; DictionaryEntry entry = new DictionaryEntry(); bool isFirst = true; Type keyType = null; Type valueType = null; for (int i = 0; i < 4; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } string property = ReadQoutedString(); // Skip colon m_Position++; if (property == "KeyType") { keyType = Type.GetType(ReadQoutedString()); } else if (property == "Key") { entry.Key = Read(keyType); } else if (property == "ValueType") { valueType = Type.GetType(ReadQoutedString()); } else if (property == "Value") { entry.Value = Read(valueType); } } result = entry; // Skip object end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { // Skip object start m_Position++; Type[] genericArgs = type.GetGenericArguments(); object key = null; object value = null; string property = ReadQoutedString(); // Skip colon m_Position++; if (property == "Key") { key = Read(genericArgs[0]); } else { value = Read(genericArgs[1]); } // Skip comma m_Position++; property = ReadQoutedString(); // Skip colon m_Position++; if (property == "Key") { key = Read(genericArgs[0]); } else { value = Read(genericArgs[1]); } result = Activator.CreateInstance(type, key, value); // Skip object end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(List <>)) { // Skip array start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetArrayLength(); IList list = (IList)Activator.CreateInstance(type); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } list.Add(Read(genericArgs[0])); } result = list; // Skip array end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(LinkedList <>)) { // Skip array start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetArrayLength(); object list = Activator.CreateInstance(type); MethodInfo addLast = type.GetMethod("AddLast", genericArgs); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } addLast.Invoke(list, new object[] { Read(genericArgs[0]) }); } result = list; // Skip array end m_Position++; } else if (isGeneric && (type.GetGenericTypeDefinition() == typeof(Dictionary <,>) || type.GetGenericTypeDefinition() == typeof(SortedDictionary <,>) || type.GetGenericTypeDefinition() == typeof(SortedList <,>))) { // Skip object start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetObjectLength(); bool isFirst = true; IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } object key = Read(genericArgs[0]); // Skip colon m_Position++; object value = Read(genericArgs[1]); dictionary.Add(key, value); } result = dictionary; // Skip object end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(Stack <>)) { // Skip array start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetArrayLength(); object stack = Activator.CreateInstance(type); MethodInfo push = type.GetMethod("Push"); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } push.Invoke(stack, new object[] { Read(genericArgs[0]) }); } result = stack; // Skip array end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(Queue <>)) { // Skip array start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetArrayLength(); object queue = Activator.CreateInstance(type); MethodInfo enqueue = type.GetMethod("Enqueue"); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } enqueue.Invoke(queue, new object[] { Read(genericArgs[0]) }); } result = queue; // Skip array end m_Position++; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(HashSet <>)) { // Skip array start m_Position++; Type[] genericArgs = type.GetGenericArguments(); int length = GetArrayLength(); object hashSet = Activator.CreateInstance(type); MethodInfo addMethod = type.GetMethod("Add"); bool isFirst = true; for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } addMethod.Invoke(hashSet, new object[] { Read(genericArgs[0]) }); } result = hashSet; // Skip array end m_Position++; } else if (type == typeof(Hashtable)) { // Skip array start m_Position++; bool isFirst = true; Hashtable hashtable = new Hashtable(); int length = GetArrayLength(); for (int i = 0; i < length; i++) { if (isFirst) { isFirst = false; } else { // Skip comma m_Position++; } DictionaryEntry entry = Read <DictionaryEntry>(); hashtable.Add(entry.Key, entry.Value); } result = hashtable; // Skip array end m_Position++; } else if (SaveGameTypeManager.HasType(type)) { // Skip object start m_Position++; m_IsFirstProperty = true; SaveGameType saveGameType = SaveGameTypeManager.GetType(type); result = saveGameType.Read(this); // Skip object end m_Position++; } else { result = ReadObject(type); } } #if !(UNITY_WSA || UNITY_WINRT) || UNITY_EDITOR if (result is IDeserializationCallback) { (result as IDeserializationCallback).OnDeserialization(this); } #endif if (nullableType != null) { Type genericType = type.GetNullableType(); result = Activator.CreateInstance(genericType, result); } return(result); }
/// <summary> /// Read the specified type. /// </summary> /// <param name="type">Type.</param> public virtual object Read(Type type) { Type nullableType = null; object result = null; if (type == null || !m_Reader.ReadBoolean()) { result = null; } else { if (Nullable.GetUnderlyingType(type) != null) { nullableType = type; type = Nullable.GetUnderlyingType(type); } bool isPrimitive = false; bool isEnum = false; bool isSerializable = false; bool isGeneric = false; #if (UNITY_WSA || UNITY_WINRT) && !UNITY_EDITOR TypeInfo info = type.GetTypeInfo(); isPrimitive = info.IsPrimitive; isEnum = info.IsEnum; isSerializable = info.IsSerializable; isGeneric = info.IsGenericType; #else isPrimitive = type.IsPrimitive; isEnum = type.IsEnum; isSerializable = type.IsSerializable; isGeneric = type.IsGenericType; #endif if (type == typeof(UnityEngine.GameObject)) { // Skip save game type start m_Reader.ReadByte(); m_Reader.ReadInt64(); int layer = ReadProperty <int>(); bool isStatic = ReadProperty <bool>(); string tag = ReadProperty <string>(); string name = ReadProperty <string>(); UnityEngine.HideFlags hideFlags = ReadProperty <UnityEngine.HideFlags>(); // Skip save game type end m_Reader.ReadByte(); UnityEngine.GameObject gameObject = new UnityEngine.GameObject(name) { layer = layer, isStatic = isStatic, tag = tag, hideFlags = hideFlags }; m_Reader.ReadString(); int count = m_Reader.ReadInt32(); for (int i = 0; i < count; i++) { string typeName = m_Reader.ReadString(); Type componentType = Type.GetType(typeName); UnityEngine.Component component = gameObject.GetComponent(componentType); if (componentType != typeof(UnityEngine.Transform) && componentType.BaseType != typeof(UnityEngine.Transform)) { UnityEngine.Component newComponent = gameObject.AddComponent(componentType); if (newComponent != null) { component = newComponent; } } ReadInto(component); } m_Reader.ReadString(); count = m_Reader.ReadInt32(); for (int i = 0; i < count; i++) { ReadChild(gameObject); } result = gameObject; } else if (isPrimitive || type == typeof(string) || type == typeof(decimal)) { if (type == typeof(string)) { result = m_Reader.ReadString(); } else if (type == typeof(decimal)) { result = m_Reader.ReadDecimal(); } else if (type == typeof(short)) { result = m_Reader.ReadInt16(); } else if (type == typeof(int)) { result = m_Reader.ReadInt32(); } else if (type == typeof(long)) { result = m_Reader.ReadInt64(); } else if (type == typeof(ushort)) { result = m_Reader.ReadUInt16(); } else if (type == typeof(uint)) { result = m_Reader.ReadUInt32(); } else if (type == typeof(ulong)) { result = m_Reader.ReadUInt64(); } else if (type == typeof(double)) { result = m_Reader.ReadDouble(); } else if (type == typeof(float)) { result = m_Reader.ReadSingle(); } else if (type == typeof(byte)) { result = m_Reader.ReadByte(); } else if (type == typeof(sbyte)) { result = m_Reader.ReadSByte(); } else if (type == typeof(char)) { result = m_Reader.ReadChar(); } else if (type == typeof(bool)) { result = m_Reader.ReadBoolean(); } } else if (isEnum) { result = Enum.Parse(type, m_Reader.ReadString()); } else if (type == typeof(DateTime)) { result = DateTime.FromBinary(m_Reader.ReadInt64()); } else if (type == typeof(TimeSpan)) { result = TimeSpan.Parse(m_Reader.ReadString()); } else if (type.IsArray) { Type elementType = type.GetElementType(); int rank = m_Reader.ReadInt32(); int[] lengths = new int[rank]; for (int i = 0; i < rank; i++) { lengths[i] = m_Reader.ReadInt32(); } Array array = Array.CreateInstance(elementType, lengths); int[] indices = new int[array.Rank]; for (int i = 0; i < array.Rank; i++) { indices[i] = array.GetLowerBound(i); } indices[array.Rank - 1]--; bool complete = false; while (!complete) { indices[array.Rank - 1]++; for (int i = array.Rank - 1; i >= 0; i--) { if (indices[i] > array.GetUpperBound(i)) { if (i == 0) { complete = true; break; } for (int j = i; j < array.Rank; j++) { indices[j] = array.GetLowerBound(j); } indices[i - 1]++; } } if (!complete) { array.SetValue(Read(elementType), indices); } } result = array; } else if (type == typeof(DictionaryEntry)) { DictionaryEntry entry = new DictionaryEntry(); Type keyType = Type.GetType(m_Reader.ReadString()); entry.Key = Read(keyType); Type valueType = Type.GetType(m_Reader.ReadString()); entry.Value = Read(valueType); result = entry; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)) { Type[] genericArgs = type.GetGenericArguments(); result = Activator.CreateInstance(type, Read(genericArgs[0]), Read(genericArgs[1])); } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(List <>)) { Type[] genericArgs = type.GetGenericArguments(); IList list = (IList)Activator.CreateInstance(type); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { list.Add(Read(genericArgs[0])); } result = list; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(LinkedList <>)) { Type[] genericArgs = type.GetGenericArguments(); object linkedList = Activator.CreateInstance(type); MethodInfo addLast = type.GetMethod("AddLast", genericArgs); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { addLast.Invoke(linkedList, new object[] { Read(genericArgs[0]) }); } result = linkedList; } else if (isGeneric && (type.GetGenericTypeDefinition() == typeof(Dictionary <,>) || type.GetGenericTypeDefinition() == typeof(SortedDictionary <,>) || type.GetGenericTypeDefinition() == typeof(SortedList <,>))) { Type[] genericArgs = type.GetGenericArguments(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); int length = m_Reader.ReadInt32(); Type keyValuePairType = typeof(KeyValuePair <,>).MakeGenericType(genericArgs); PropertyInfo keyProperty = keyValuePairType.GetProperty("Key", TypeUtils.SavableBindingFlags); PropertyInfo valueProperty = keyValuePairType.GetProperty("Value", TypeUtils.SavableBindingFlags); for (int i = 0; i < length; i++) { object keyValuePair = Read(keyValuePairType); dictionary.Add(keyProperty.GetValue(keyValuePair, null), valueProperty.GetValue(keyValuePair, null)); } result = dictionary; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(Stack <>)) { Type[] genericArgs = type.GetGenericArguments(); object stack = Activator.CreateInstance(type); MethodInfo push = type.GetMethod("Push"); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { push.Invoke(stack, new object[] { Read(genericArgs[0]) }); } result = stack; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(Queue <>)) { Type[] genericArgs = type.GetGenericArguments(); object queue = Activator.CreateInstance(type); MethodInfo enqueue = type.GetMethod("Enqueue"); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { enqueue.Invoke(queue, new object[] { Read(genericArgs[0]) }); } result = queue; } else if (isGeneric && type.GetGenericTypeDefinition() == typeof(HashSet <>)) { Type[] genericArgs = type.GetGenericArguments(); object hashSet = Activator.CreateInstance(type); MethodInfo addMethod = type.GetMethod("Add"); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { addMethod.Invoke(hashSet, new object[] { Read(genericArgs[0]) }); } result = hashSet; } else if (type == typeof(Hashtable)) { Hashtable hashtable = new Hashtable(); int length = m_Reader.ReadInt32(); for (int i = 0; i < length; i++) { DictionaryEntry entry = Read <DictionaryEntry>(); hashtable.Add(entry.Key, entry.Value); } result = hashtable; } else if (SaveGameTypeManager.HasType(type)) { // Skip save game type start m_Reader.ReadByte(); m_Reader.ReadInt64(); SaveGameType saveGameType = SaveGameTypeManager.GetType(type); result = saveGameType.Read(this); // Skip save game type end m_Reader.ReadByte(); } else { result = ReadObject(type); } } #if !(UNITY_WSA || UNITY_WINRT) || UNITY_EDITOR if (result is IDeserializationCallback) { (result as IDeserializationCallback).OnDeserialization(this); } #endif if (nullableType != null) { Type genericType = type.GetNullableType(); result = Activator.CreateInstance(genericType, result); } return(result); }