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);
 public StandartSerializeResult(int realLength, StandartSerializeResult composeSerializeResult)
 {
     Bytes  = new byte[realLength];
     Length = realLength;
     _composeSerializeResult = composeSerializeResult;
 }