public static void ReadAndMapProperty(this Stream stream, object obj, List<string> nameTable) { var baseProperty = stream.ReadBaseProperty(); var pi = obj.GetType().GetField(nameTable[baseProperty.NameIdx], BindingFlags.Public | BindingFlags.Instance); if (pi == null) return; var fieldType = pi.FieldType.IsGenericType && pi.FieldType.GetGenericTypeDefinition() == typeof (Nullable<>) ? Nullable.GetUnderlyingType(pi.FieldType) : pi.FieldType; object value = null; switch (nameTable[baseProperty.TypeIdx]) { case "IntProperty": value = stream.ReadInt32(); break; case "BoolProperty": value = stream.ReadBool(); break; case "ByteProperty": stream.ReadInt32(); // EnumNameIdx var enumValueNameIdx = stream.ReadInt32(); value = Enum.Parse(fieldType, nameTable[enumValueNameIdx]); break; case "FloatProperty": value = stream.ReadFloat(); break; case "NameProperty": value = stream.ReadNameProperty(nameTable); break; case "StrProperty": value = stream.ReadString(); break; case "ArrayProperty": // У массивов NumElements входит в PropertySize var numElements = stream.ReadInt32(); // Если элементов нет, то следом идет сразу следующее свойство, массив не заканчивается ничем, нет даже None if (numElements == 0) return; value = Activator.CreateInstance(fieldType); var elementType = fieldType.GetGenericArguments()[0]; for (var i = 0; i < numElements; i++) { if (elementType == typeof (int)) // array<int> { (value as IList).Add(stream.ReadInt32()); } else if (elementType == typeof (string)) // array<string> { (value as IList).Add(stream.ReadString()); } else if (elementType == typeof (NameProperty)) // array<name> { (value as IList).Add(stream.ReadNameProperty(nameTable)); } else { var element = Activator.CreateInstance(elementType); var nameIdx = stream.ReadInt32(); while (nameTable[nameIdx] != "None") { stream.Seek(-4, SeekOrigin.Current); stream.ReadAndMapProperty(element, nameTable); nameIdx = stream.ReadInt32(); } (value as IList).Add(element); } } break; case "StructProperty": // У структур StructNameIdx не входит в PropertySize var structNameIdx = stream.ReadInt32(); switch (nameTable[structNameIdx]) { case "Vector": value = new Vector { X = stream.ReadFloat(), Y = stream.ReadFloat(), Z = stream.ReadFloat() }; break; case "Rotator": value = new Rotator { Pitch = stream.ReadInt32(), Yaw = stream.ReadInt32(), Roll = stream.ReadInt32() }; break; case "Transform": stream.Seek(baseProperty.PropertySize, SeekOrigin.Current); break; default: // На случай SEpisodeBoundaryStats[] value = Activator.CreateInstance(fieldType.IsArray ? fieldType.GetElementType() : fieldType); var nameIdx = stream.ReadInt32(); // None в конце всех структур, кроме стандартных Vector, Rotator, Transform while (nameTable[nameIdx] != "None") { stream.Seek(-4, SeekOrigin.Current); stream.ReadAndMapProperty(value, nameTable); nameIdx = stream.ReadInt32(); } break; } break; } if (fieldType.IsArray) { var array = (Array) pi.GetValue(obj); array.SetValue(value, baseProperty.ArrayIdx); pi.SetValue(obj, array); } else { pi.SetValue(obj, value); } }
public static void ReadAndMapProperty(this Stream stream, object obj, List <string> nameTable) { var baseProperty = stream.ReadBaseProperty(); var pi = obj.GetType().GetField(nameTable[baseProperty.NameIdx], BindingFlags.Public | BindingFlags.Instance); if (pi == null) { return; } var fieldType = pi.FieldType.IsGenericType && pi.FieldType.GetGenericTypeDefinition() == typeof(Nullable <>) ? Nullable.GetUnderlyingType(pi.FieldType) : pi.FieldType; object value = null; switch (nameTable[baseProperty.TypeIdx]) { case "IntProperty": value = stream.ReadInt32(); break; case "BoolProperty": value = stream.ReadBool(); break; case "ByteProperty": stream.ReadInt32(); // EnumNameIdx var enumValueNameIdx = stream.ReadInt32(); value = Enum.Parse(fieldType, nameTable[enumValueNameIdx]); break; case "FloatProperty": value = stream.ReadFloat(); break; case "NameProperty": value = stream.ReadNameProperty(nameTable); break; case "StrProperty": value = stream.ReadString(); break; case "ArrayProperty": // У массивов NumElements входит в PropertySize var numElements = stream.ReadInt32(); // Если элементов нет, то следом идет сразу следующее свойство, массив не заканчивается ничем, нет даже None if (numElements == 0) { return; } value = Activator.CreateInstance(fieldType); var elementType = fieldType.GetGenericArguments()[0]; for (var i = 0; i < numElements; i++) { if (elementType == typeof(int)) // array<int> { (value as IList).Add(stream.ReadInt32()); } else if (elementType == typeof(string)) // array<string> { (value as IList).Add(stream.ReadString()); } else if (elementType == typeof(NameProperty)) // array<name> { (value as IList).Add(stream.ReadNameProperty(nameTable)); } else { var element = Activator.CreateInstance(elementType); var nameIdx = stream.ReadInt32(); while (nameTable[nameIdx] != "None") { stream.Seek(-4, SeekOrigin.Current); stream.ReadAndMapProperty(element, nameTable); nameIdx = stream.ReadInt32(); } (value as IList).Add(element); } } break; case "StructProperty": // У структур StructNameIdx не входит в PropertySize var structNameIdx = stream.ReadInt32(); switch (nameTable[structNameIdx]) { case "Vector": value = new Vector { X = stream.ReadFloat(), Y = stream.ReadFloat(), Z = stream.ReadFloat() }; break; case "Rotator": value = new Rotator { Pitch = stream.ReadInt32(), Yaw = stream.ReadInt32(), Roll = stream.ReadInt32() }; break; case "Transform": stream.Seek(baseProperty.PropertySize, SeekOrigin.Current); break; default: // На случай SEpisodeBoundaryStats[] value = Activator.CreateInstance(fieldType.IsArray ? fieldType.GetElementType() : fieldType); var nameIdx = stream.ReadInt32(); // None в конце всех структур, кроме стандартных Vector, Rotator, Transform while (nameTable[nameIdx] != "None") { stream.Seek(-4, SeekOrigin.Current); stream.ReadAndMapProperty(value, nameTable); nameIdx = stream.ReadInt32(); } break; } break; } if (fieldType.IsArray) { var array = (Array)pi.GetValue(obj); array.SetValue(value, baseProperty.ArrayIdx); pi.SetValue(obj, array); } else { pi.SetValue(obj, value); } }