/// <summary> /// Deserializes a property of a structure. /// </summary> /// <param name="reader">The reader.</param> /// <param name="context">The serialization context to use.</param> /// <param name="instance">The instance to store the property to.</param> /// <param name="tagFieldInfo">The active element enumerator.</param> /// <param name="baseOffset">The offset of the start of the structure.</param> /// <exception cref="System.InvalidOperationException">Offset for property is outside of its structure</exception> public void DeserializeProperty(EndianReader reader, ISerializationContext context, object instance, TagFieldInfo tagFieldInfo, long baseOffset) { var attr = tagFieldInfo.Attribute; if (attr.Flags.HasFlag(Runtime) || !CacheVersionDetection.AttributeInCacheVersion(attr, Version)) { return; } if (tagFieldInfo.FieldType.IsArray && attr.Flags.HasFlag(Relative)) { var type = instance.GetType(); var field = type.GetField( attr.Field, BindingFlags.Instance | BindingFlags.Public); var attr2 = TagStructure.GetTagFieldAttribute(type, field); if (CacheVersionDetection.AttributeInCacheVersion(attr2, Version)) { attr.Length = (int)Convert.ChangeType(field.GetValue(instance), typeof(int)); } else { throw new InvalidOperationException(attr2.Field); } } if (attr.Flags.HasFlag(Padding)) { #if DEBUG var unused = reader.ReadBytes(attr.Length); foreach (var b in unused) { if (b != 0) { Console.WriteLine($"WARNING: non-zero padding found in {tagFieldInfo.FieldInfo.DeclaringType.FullName}.{tagFieldInfo.FieldInfo.Name} = {b}"); break; } } #else reader.BaseStream.Position += attr.Length; #endif } else { var value = DeserializeValue(reader, context, attr, tagFieldInfo.FieldType); tagFieldInfo.SetValue(instance, value); } }
/// <summary> /// Builds the <see cref="Tags.TagFieldInfo"/> <see cref="List{T}"/> to be enumerated. /// </summary> private void Build() { uint offset = 0; // Build the field list. Scan through the type's inheritance // hierarchy and add any fields belonging to tag structures. foreach (var type in Info.Types.Reverse <Type>()) { // Ensure that fields are in declaration order - GetFields does NOT guarantee foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).OrderBy(i => i.MetadataToken)) { var attr = TagStructure.GetTagFieldAttribute(type, field); if (CacheVersionDetection.AttributeInCacheVersion(attr, Info.Version)) { CreateTagFieldInfo(field, attr, Info.Version, ref offset); } } } }