Esempio n. 1
0
        public void RegisterConverter(BinaryConverter converter)
        {
            var converterType = converter.GetType();
            var type          = converterType.BaseType;

            if (type == null)
            {
                throw BinaryException.ConverterError(converterType.Name);
            }

            var genericType = type.GenericTypeArguments.Single();

            _customConverters.TryAdd(genericType, converter);
        }
        private static StandartSerializeResult InternalSerialize(object data, BinarySerializerContext context)
        {
            int realLength;

            byte[] serializedBody = null;
            StandartSerializeResult composeSerializeResult = null;
            var examined = 0;

            if (context.ReflectionData.BodyProperty != null)
            {
                var bodyValue = context.ReflectionData.BodyProperty.Get(data);

                if (bodyValue == null)
                {
                    throw BinaryException.SerializerBodyPropertyIsNull();
                }

                serializedBody = context.BitConverterHelper.ConvertToBytes(bodyValue, context.ReflectionData.BodyProperty.Type, context.ReflectionData.BodyProperty.Attribute.Reverse);
                realLength     = CalculateRealLength(context.ReflectionData.LengthProperty, data, context.ReflectionData.MetaLength, serializedBody.Length);
            }
            else if (context.ReflectionData.ComposeProperty != null)
            {
                var composeValue = context.ReflectionData.ComposeProperty.Get(data);

                if (composeValue == null)
                {
                    throw BinaryException.SerializerComposePropertyIsNull();
                }

                if (context.ReflectionData.ComposeProperty.Type.IsPrimitive)
                {
                    serializedBody = context.BitConverterHelper.ConvertToBytes(composeValue, context.ReflectionData.ComposeProperty.Type, context.ReflectionData.ComposeProperty.Attribute.Reverse);
                    realLength     = CalculateRealLength(context.ReflectionData.LengthProperty, data, context.ReflectionData.MetaLength, serializedBody.Length);
                }
                else
                {
                    var composeContext = BinaryCache.GetOrAddContext(context.ReflectionData.ComposeProperty.Type, context.BitConverterHelper);
                    composeSerializeResult = InternalSerialize(composeValue, composeContext);
                    realLength             = CalculateRealLength(context.ReflectionData.LengthProperty, data, context.ReflectionData.MetaLength, composeSerializeResult.Length);
                }
            }
            else
            {
                realLength = context.ReflectionData.MetaLength;
            }

            var serializeResult = new StandartSerializeResult(realLength, composeSerializeResult);
            var bytes           = serializeResult.Bytes;

            foreach (var property in context.ReflectionData.Properties)
            {
                if (!property.Type.IsPrimitive && property.Attribute.BinaryDataType == BinaryDataType.Compose && composeSerializeResult != null)
                {
                    Array.Copy(
                        composeSerializeResult.Bytes,
                        0,
                        bytes,
                        property.Attribute.Index,
                        composeSerializeResult.Length
                        );
                }
                else
                {
                    var value = property.Attribute.BinaryDataType == BinaryDataType.Body || property.Attribute.BinaryDataType == BinaryDataType.Compose
                        ? serializedBody ?? throw BinaryException.SerializerBodyPropertyIsNull()
                        : context.BitConverterHelper.ConvertToBytes(property.Get(data), property.Type, property.Attribute.Reverse);

                    var valueLength = value.Length;

                    if (property.Attribute.BinaryDataType != BinaryDataType.Body && property.Attribute.BinaryDataType != BinaryDataType.Compose && valueLength > property.Attribute.Length)
                    {
                        throw BinaryException.SerializerLengthOutOfRange(property.Type.ToString(), valueLength.ToString(), property.Attribute.Length.ToString());
                    }

                    value.CopyTo(bytes, property.Attribute.Index);
                }

                if (++examined == context.ReflectionData.Properties.Count)
                {
                    break;
                }
            }

            return(serializeResult);
        private static void EnsureTypeHasRequiredAttributes(Type typeData)
        {
            var members = GetMembers(typeData).ToArray();

            var key = members.Where(item => GetTcpDataAttribute(item.Member).BinaryDataType == BinaryDataType.Id).ToList();

            if (key.Count > 1)
            {
                throw BinaryException.AttributeDuplicate(typeData.ToString(), nameof(BinaryDataType.Id));
            }

            if (key.Count == 1 && key.Single() is { IsProperty : true } internalMember1&& !CanReadWrite((PropertyInfo)internalMember1.Member))
            {
                throw BinaryException.PropertyCanReadWrite(typeData.ToString(), nameof(BinaryDataType.Id));
            }

            var body = members.Where(item => GetTcpDataAttribute(item.Member).BinaryDataType == BinaryDataType.Body).ToList();

            if (body.Count > 1)
            {
                throw BinaryException.AttributeDuplicate(typeData.ToString(), nameof(BinaryDataType.Body));
            }

            if (body.Count == 1 && body.Single() is { IsProperty : true } internalMember2&& !CanReadWrite((PropertyInfo)internalMember2.Member))
            {
                throw BinaryException.PropertyCanReadWrite(typeData.ToString(), nameof(BinaryDataType.Body));
            }

            var compose = members.Where(item => GetTcpDataAttribute(item.Member).BinaryDataType == BinaryDataType.Compose).ToList();

            if (compose.Count > 1)
            {
                throw BinaryException.AttributeDuplicate(typeData.ToString(), nameof(BinaryDataType.Compose));
            }

            if (body.Count == 1 && compose.Count == 1)
            {
                throw BinaryException.AttributeBodyAndComposeViolated(typeData.ToString());
            }

            var length = members.Where(item => GetTcpDataAttribute(item.Member).BinaryDataType == BinaryDataType.Length).ToList();

            if (length.Count > 1)
            {
                throw BinaryException.AttributeDuplicate(typeData.ToString(), nameof(BinaryDataType.Length));
            }

            if (body.Count == 1)
            {
                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (length.Count == 0)
                {
                    throw BinaryException.AttributeLengthRequired(typeData.ToString(), nameof(BinaryDataType.Body));
                }

                if (length.Count == 1 && length.Single() is { IsProperty : true } internalMember3&& !CanReadWrite((PropertyInfo)internalMember3.Member))
                {
                    throw BinaryException.PropertyCanReadWrite(typeData.ToString(), nameof(BinaryDataType.Length));
                }
            }
            else if (compose.Count == 1)
            {
                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (length.Count == 0)
                {
                    throw BinaryException.AttributeLengthRequired(typeData.ToString(), nameof(BinaryDataType.Compose));
                }

                if (length.Count == 1 && length.Single() is { IsProperty : true } internalMember4&& !CanReadWrite((PropertyInfo)internalMember4.Member))
                {
                    throw BinaryException.PropertyCanReadWrite(typeData.ToString(), nameof(BinaryDataType.Length));
                }
            }
            else if (length.Count == 1)
            {
                throw BinaryException.AttributeRequiredWithLength(typeData.ToString());
            }

            var metaData = members.Where(item => GetTcpDataAttribute(item.Member).BinaryDataType == BinaryDataType.MetaData).ToList();

            if (key.Count == 0 && length.Count == 0 && body.Count == 0 && metaData.Count == 0)
            {
                throw BinaryException.AttributesRequired(typeData.ToString());
            }

            foreach (var item in metaData.Where(item => item.IsProperty && !CanReadWrite((PropertyInfo)item.Member)))
            {
                throw BinaryException.PropertyCanReadWrite(typeData.ToString(), nameof(BinaryDataType.MetaData), GetTcpDataAttribute(item.Member).Index.ToString());
            }