/// <summary> /// Collect properties information of the given object. /// </summary> private static IEnumerable <ValueToFormat> CollectPropertiesForWriting(object obj) { var type = obj.GetType(); return(from prop in type.GetProperties() let val = prop.GetValue(obj, Array.Empty <object>()) let isArray = prop.PropertyType.IsArray select new ValueToFormat { Value = val, IsArray = isArray, Format = val == null ? PiffDataFormats.Skip : prop.GetCustomAttribute <PiffDataFormatAttribute>()?.Format ?? (isArray ? PiffDataUtility.GetDefaultFormat(prop.PropertyType.GetElementType()) : PiffDataUtility.GetDefaultFormat(prop.PropertyType)) }); }
/// <summary> /// Read a box if it is of expected type. Back off if it's not. /// </summary> /// <param name="expectedType">Expected box type</typeparam> /// <param name="bytes"></param> /// <returns>Box object or null</returns> internal static object ReadBox(Stream bytes, Type expectedType) { var length = GetInt32(bytes); if (length < 8) { throw new ArgumentException($"Improper box length {length}."); } var id = GetFixedString(bytes, 4); if (!sBoxes.TryGetValue(id, out var type)) { throw new ArgumentException($"Inrecognized box type '{id}'."); } if (type != expectedType) { // Not expected type, back off bytes.Seek(-8, SeekOrigin.Current); return(null); } var obj = Activator.CreateInstance(type); var props = from prop in type.GetProperties() let isArray = prop.PropertyType.IsArray select new ValueToRead { Property = prop, IsArray = isArray, Format = prop.GetCustomAttribute <PiffDataFormatAttribute>()?.Format ?? (isArray ? PiffDataUtility.GetDefaultFormat(prop.PropertyType.GetElementType()) : PiffDataUtility.GetDefaultFormat(prop.PropertyType)) }; ReadBoxValues(bytes, obj, props.ToArray()); return(obj); }