private void ValidatePropertyInfo(PropertyInfo prop) { // Get a possible binary member configuration or use the default one. BinaryMemberAttribute attrib = prop.GetCustomAttribute <BinaryMemberAttribute>(); bool hasAttrib = attrib != null; attrib = attrib ?? new BinaryMemberAttribute(); // Property must have getter and setter - if not, throw an exception if it is explicitly decorated. if (hasAttrib && (prop.GetMethod == null || prop.SetMethod == null)) { throw new InvalidOperationException($"Getter and setter on property {prop} not found."); } // Property must be decorated or getter and setter public. if (hasAttrib || (!Attribute.Explicit && prop.GetMethod?.IsPublic == true && prop.SetMethod?.IsPublic == true)) { // For properties of enumerable type ElementCount must be specified. if (prop.PropertyType.IsEnumerable() && attrib.Length <= 0) { throw new InvalidOperationException( $"Property {prop} requires an element count specified with a {nameof(BinaryMemberAttribute)}."); } Members.Add(new MemberData(prop, prop.PropertyType, attrib)); } }
// ---- METHODS (PRIVATE) -------------------------------------------------------------------------------------- private void ValidateFieldInfo(FieldInfo field) { // Get a possible binary member configuration or use the default one. BinaryMemberAttribute attrib = field.GetCustomAttribute <BinaryMemberAttribute>(); bool hasAttrib = attrib != null; attrib = attrib ?? new BinaryMemberAttribute(); // Field must be decorated or public. if (hasAttrib || (!Attribute.Explicit && field.IsPublic)) { // For fields of enumerable type ElementCount must be specified. if (field.FieldType.IsEnumerable() && attrib.Length <= 0) { throw new InvalidOperationException( $"Field {field} requires an element count specified with a {nameof(BinaryMemberAttribute)}."); } // Store member in a deterministic order. MemberData memberData = new MemberData(field, field.FieldType, attrib); if (attrib.Order == Int32.MinValue) { UnorderedMembers.Add(field.Name, memberData); } else { OrderedMembers.Add(attrib.Order, memberData); } } }
private void WriteObject(object instance, BinaryMemberAttribute attribute, Type type, object value) { if (attribute.Converter == null) { if (value == null) { return; } if (type == typeof(String)) { Write((String)value, attribute.StringFormat); } else if (type.TryGetEnumerableElementType(out Type elementType)) { foreach (object element in (IEnumerable)value) { WriteObject(null, BinaryMemberAttribute.Default, elementType, element); } } else if (type == typeof(Boolean)) { Write((Boolean)value, attribute.BooleanFormat); } else if (type == typeof(Byte)) { Write((Byte)value); } else if (type == typeof(DateTime)) { Write((DateTime)value, attribute.DateTimeFormat); } else if (type == typeof(Decimal)) { Write((Decimal)value); } else if (type == typeof(Double)) { Write((Double)value); } else if (type == typeof(Int16)) { Write((Int16)value); } else if (type == typeof(Int32)) { Write((Int32)value); } else if (type == typeof(Int64)) { Write((Int64)value); } else if (type == typeof(SByte)) { Write((SByte)value); } else if (type == typeof(Single)) { Write((Single)value); } else if (type == typeof(UInt16)) { Write((UInt16)value); } else if (type == typeof(UInt32)) { Write((UInt32)value); } else if (type == typeof(UInt64)) { Write((UInt32)value); } else if (type.GetTypeInfo().IsEnum) { WriteEnum(type, value, attribute.Strict); } else { WriteCustomObject(type, value, Position); } } else { // Let a converter do all the work. IBinaryConverter converter = BinaryConverterCache.GetConverter(attribute.Converter); converter.Write(this, instance, attribute, value); } }
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="MemberData"/> class for the given <paramref name="memberInfo"/> /// with the specified <paramref name="attribute"/> configuration. /// </summary> /// <param name="memberInfo">The <see cref="MemberData"/> to represent.</param> /// <param name="type">The type of the value stored by the member.</param> /// <param name="attribute">The <see cref="BinaryMemberAttribute"/> configuration.</param> internal MemberData(MemberInfo memberInfo, Type type, BinaryMemberAttribute attribute) { MemberInfo = memberInfo; Type = type; Attribute = attribute; }
private object ReadObject(object instance, BinaryMemberAttribute attribute, Type type) { if (attribute.Converter == null) { if (type == typeof(String)) { if (attribute.StringFormat == StringDataFormat.Raw) { return(ReadString(attribute.Length)); } else { return(ReadString(attribute.StringFormat)); } } else if (type.IsEnumerable()) { throw new InvalidOperationException("Multidimensional arrays cannot be read directly."); } else if (type == typeof(Boolean)) { return(ReadBoolean(attribute.BooleanFormat)); } else if (type == typeof(Byte)) { return(ReadByte()); } else if (type == typeof(DateTime)) { return(ReadDateTime(attribute.DateTimeFormat)); } else if (type == typeof(Decimal)) { return(ReadDecimal()); } else if (type == typeof(Double)) { return(ReadDouble()); } else if (type == typeof(Int16)) { return(ReadInt16()); } else if (type == typeof(Int32)) { return(ReadInt32()); } else if (type == typeof(Int64)) { return(ReadInt64()); } else if (type == typeof(SByte)) { return(ReadSByte()); } else if (type == typeof(Single)) { return(ReadSingle()); } else if (type == typeof(UInt16)) { return(ReadUInt16()); } else if (type == typeof(UInt32)) { return(ReadUInt32()); } else if (type == typeof(UInt64)) { return(ReadUInt64()); } else if (type.GetTypeInfo().IsEnum) { return(ReadEnum(type, attribute.Strict)); } else { return(ReadCustomObject(type, null, Position)); } } else { // Let a converter do all the work. IBinaryConverter converter = BinaryConverterCache.GetConverter(attribute.Converter); return(converter.Read(this, instance, attribute)); } }
private static void WriteObject(Stream stream, object instance, BinaryMemberAttribute attribute, Type type, object value, ByteConverter converter) { converter = converter ?? ByteConverter.System; if (attribute.Converter == null) { if (value == null) { return; } else if (type == typeof(String)) { stream.Write((String)value, attribute.StringFormat, converter: converter); } else if (type.TryGetEnumerableElementType(out Type elementType)) { foreach (object element in (IEnumerable)value) { WriteObject(stream, null, BinaryMemberAttribute.Default, elementType, element, converter); } } else if (type == typeof(Boolean)) { stream.Write((Boolean)value, attribute.BooleanFormat, converter); } else if (type == typeof(Byte)) { stream.Write((Byte)value); } else if (type == typeof(DateTime)) { stream.Write((DateTime)value, attribute.DateTimeFormat, converter); } else if (type == typeof(Decimal)) { stream.Write((Decimal)value); } else if (type == typeof(Double)) { stream.Write((Double)value, converter); } else if (type == typeof(Int16)) { stream.Write((Int16)value, converter); } else if (type == typeof(Int32)) { stream.Write((Int32)value, converter); } else if (type == typeof(Int64)) { stream.Write((Int64)value, converter); } else if (type == typeof(SByte)) { stream.Write((SByte)value); } else if (type == typeof(Single)) { stream.Write((Single)value, converter); } else if (type == typeof(UInt16)) { stream.Write((UInt16)value, converter); } else if (type == typeof(UInt32)) { stream.Write((UInt32)value, converter); } else if (type == typeof(UInt64)) { stream.Write((UInt64)value, converter); } else if (type.IsEnum) { WriteEnum(stream, type, value, attribute.Strict, converter); } else { if (stream.CanSeek) { WriteCustomObject(stream, type, value, stream.Position, converter); } else { WriteCustomObject(stream, type, value, -1, converter); } } } else { // Let a binary converter do all the work. IBinaryConverter binaryConverter = BinaryConverterCache.GetConverter(attribute.Converter); binaryConverter.Write(stream, instance, attribute, value, converter); } }
private static object ReadObject(Stream stream, object instance, BinaryMemberAttribute attribute, Type type, ByteConverter converter) { if (attribute.Converter == null) { if (type == typeof(String)) { if (attribute.StringFormat == StringCoding.Raw) { return(stream.ReadString(attribute.Length)); } else { return(stream.ReadString(attribute.StringFormat, converter: converter)); } } else if (type.IsEnumerable()) { throw new InvalidOperationException("Multidimensional arrays cannot be read directly."); } else if (type == typeof(Boolean)) { return(stream.ReadBoolean(attribute.BooleanFormat)); } else if (type == typeof(Byte)) { return(stream.Read1Byte()); } else if (type == typeof(DateTime)) { return(stream.ReadDateTime(attribute.DateTimeFormat, converter)); } else if (type == typeof(Decimal)) { return(stream.ReadDecimal()); } else if (type == typeof(Double)) { return(stream.ReadDouble(converter)); } else if (type == typeof(Int16)) { return(stream.ReadInt16(converter)); } else if (type == typeof(Int32)) { return(stream.ReadInt32(converter)); } else if (type == typeof(Int64)) { return(stream.ReadInt64(converter)); } else if (type == typeof(SByte)) { return(stream.ReadSByte()); } else if (type == typeof(Single)) { return(stream.ReadSingle(converter)); } else if (type == typeof(UInt16)) { return(stream.ReadUInt16(converter)); } else if (type == typeof(UInt32)) { return(stream.ReadUInt32(converter)); } else if (type == typeof(UInt64)) { return(stream.ReadUInt64(converter)); } else if (type.IsEnum) { return(ReadEnum(stream, type, attribute.Strict, converter)); } else { if (stream.CanSeek) { return(ReadCustomObject(stream, type, null, stream.Position, converter)); } else { return(ReadCustomObject(stream, type, null, -1, converter)); } } } else { // Let a binary converter do all the work. IBinaryConverter binaryConverter = BinaryConverterCache.GetConverter(attribute.Converter); return(binaryConverter.Read(stream, instance, attribute, converter)); } }