List <LogicalMessage> Extract(IncomingMessage physicalMessage)
    {
        if (physicalMessage.Body == null || physicalMessage.Body.Length == 0)
        {
            return(new List <LogicalMessage>());
        }

        var messageMetadata = new List <MessageMetadata>();

        var headers = physicalMessage.Headers;

        if (headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageTypeIdentifier))
        {
            foreach (var messageTypeString in messageTypeIdentifier.Split(';'))
            {
                var typeString = messageTypeString;
                var metadata   = messageMetadataRegistry.GetMessageMetadata(typeString);
                if (metadata == null)
                {
                    continue;
                }

                messageMetadata.Add(metadata);
            }

            if (
                messageMetadata.Count == 0 &&
                physicalMessage.GetMessageIntent() != MessageIntentEnum.Publish)
            {
                log.Warn($"Could not determine message type from message header '{messageTypeIdentifier}'. MessageId: {physicalMessage.MessageId}");
            }
        }

        using (var stream = new MemoryStream(physicalMessage.Body))
        {
            var messageSerializer  = serializationMapper.GetSerializer(headers);
            var typesToDeserialize = messageMetadata
                                     .Select(metadata => metadata.MessageType)
                                     .ToList();
            return(messageSerializer.Deserialize(stream, typesToDeserialize)
                   .Select(x => logicalMessageFactory.Create(x.GetType(), x))
                   .ToList());
        }
    }
        LogicalMessage[] Extract(IncomingMessage physicalMessage)
        {
            // We need this check to be compatible with v3.3 endpoints, v3.3 control messages also include a body
            if (IsControlMessage(physicalMessage))
            {
                log.Debug("Received a control message. Skipping deserialization as control message data is contained in the header.");
                return(NoMessagesFound);
            }

            if (physicalMessage.Body == null || physicalMessage.Body.Length == 0)
            {
                log.Debug("Received a message without body. Skipping deserialization.");
                return(NoMessagesFound);
            }

            var messageMetadata = new List <MessageMetadata>();

            if (physicalMessage.Headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageTypeIdentifier))
            {
                foreach (var messageTypeString in messageTypeIdentifier.Split(EnclosedMessageTypeSeparator))
                {
                    var typeString = messageTypeString;

                    if (DoesTypeHaveImplAddedByVersion3(typeString))
                    {
                        continue;
                    }

                    MessageMetadata metadata;

                    if (IsV4OrBelowScheduledTask(typeString))
                    {
                        metadata = messageMetadataRegistry.GetMessageMetadata(typeof(ScheduledTask));
                    }
                    else
                    {
                        metadata = messageMetadataRegistry.GetMessageMetadata(typeString);
                    }

                    if (metadata == null)
                    {
                        continue;
                    }

                    messageMetadata.Add(metadata);
                }

                if (messageMetadata.Count == 0 && physicalMessage.GetMessageIntent() != MessageIntentEnum.Publish)
                {
                    log.WarnFormat("Could not determine message type from message header '{0}'. MessageId: {1}", messageTypeIdentifier, physicalMessage.MessageId);
                }
            }

            var messageTypes      = messageMetadata.Select(metadata => metadata.MessageType).ToList();
            var messageSerializer = deserializerResolver.Resolve(physicalMessage.Headers);

            mapper.Initialize(messageTypes);

            // For nested behaviors who have an expectation ContentType existing
            // add the default content type
            physicalMessage.Headers[Headers.ContentType] = messageSerializer.ContentType;

            using (var stream = new MemoryStream(physicalMessage.Body))
            {
                var deserializedMessages = messageSerializer.Deserialize(stream, messageTypes);
                var logicalMessages      = new LogicalMessage[deserializedMessages.Length];
                for (var i = 0; i < deserializedMessages.Length; i++)
                {
                    var x = deserializedMessages[i];
                    logicalMessages[i] = logicalMessageFactory.Create(x.GetType(), x);
                }
                return(logicalMessages);
            }
        }