/// <summary>
        /// Reads a new serialized message object from the base stream and deserializes it.
        /// </summary>
        /// <param name="readTimeOutSeconds">Optional read timeout in seconds  (0 means no timeout).</param>
        /// <returns>
        /// The deserialized object if successful, <c>null</c> otherwise.
        /// </returns>
        public object Read(int readTimeOutSeconds = 0)
        {
            try
            {
                lock (_readSerializerMap)
                {
                    if (_readSerializerMap.Count == 0)
                    {
                        return(false);
                    }

                    XmlSerializer serializer = null;
                    byte[]        message    = null;

                    do
                    {
                        if ((message = _stream.Read(readTimeOutSeconds)) == null)
                        {
                            return(null);
                        }

                        int    descriptorLength  = (message.Length < TypeDescriptorMaxLength) ? message.Length : TypeDescriptorMaxLength;
                        string typeDescriptor    = Encoding.UTF8.GetString(message, 0, descriptorLength);
                        Match  objectTypeMatch   = _messageObjectTypeRegex.Match(typeDescriptor);
                        string messageObjectType = objectTypeMatch.Groups["objectType"].Value;

                        if ((objectTypeMatch.Success == false) || (string.IsNullOrWhiteSpace(messageObjectType)))
                        {
                            this.Error("The read object does not have a valid type.\r\n{0}\r\n", typeDescriptor);
                            return(null);
                        }

                        messageObjectType = messageObjectType.Trim().ToLower();

                        if (_readSerializerMap.ContainsKey(messageObjectType) == false)
                        {
                            this.Error("The object type '{0}' is not supported.", messageObjectType);
                        }
                        else
                        {
                            serializer = _readSerializerMap[messageObjectType];
                        }
                    }while (serializer == null);

                    using (MemoryStream ms = new MemoryStream(message))
                    {
                        return(serializer.Deserialize(ms));
                    }
                }
            }
            catch (Exception ex)
            {
                this.Error("Reading serialized object failed.", ex);
            }

            return(null);
        }
        /// <summary>
        /// Reads a new serialized message object from the base stream and deserializes it.
        /// </summary>
        /// <param name="readTimeOutSeconds">Optional read timeout in seconds  (0 means no timeout).</param>
        /// <returns>
        /// The deserialized object if successful, <c>null</c> otherwise.
        /// </returns>
        public object Read(int readTimeOutSeconds = 0)
        {
            try
            {
                lock (_readSerializerMap)
                {
                    if (_readSerializerMap.Count == 0)
                    {
                        return(false);
                    }

                    XmlSerializer serializer = null;
                    byte[]        message    = null;

                    bool isUnprocessedMessage = false;

                    do
                    {
                        if ((message = _stream.Read(readTimeOutSeconds)) == null)
                        {
                            return(null);
                        }

                        int    descriptorLength  = (message.Length < TypeDescriptorMaxLength) ? message.Length : TypeDescriptorMaxLength;
                        string typeDescriptor    = Encoding.UTF8.GetString(message, 0, descriptorLength);
                        Match  objectTypeMatch   = _messageObjectTypeRegex.Match(typeDescriptor);
                        string messageObjectType = objectTypeMatch.Groups["objectType"].Value;

                        isUnprocessedMessage = (String.Equals(messageObjectType, typeof(UnprocessedMessage).Name));

                        if ((objectTypeMatch.Success == false) || (string.IsNullOrWhiteSpace(messageObjectType)))
                        {
                            this.Error($"The read object does not have a valid type: { Environment.NewLine }'{ typeDescriptor }'{ Environment.NewLine }");

                            if (isUnprocessedMessage == false)
                            {
                                this.Write(Utils.CreateUnprocessedMessage(Encoding.UTF8.GetString(message), UnprocessedMessageReason.SyntaxError));
                            }
                            return(null);
                        }

                        messageObjectType = messageObjectType.Trim().ToLower();

                        if (_readSerializerMap.ContainsKey(messageObjectType) == false)
                        {
                            this.Error("The object type '{0}' is not supported.", messageObjectType);

                            if (isUnprocessedMessage == false)
                            {
                                this.Write(Utils.CreateUnprocessedMessage(Encoding.UTF8.GetString(message), UnprocessedMessageReason.NotSupported));
                            }
                        }
                        else
                        {
                            serializer = _readSerializerMap[messageObjectType];
                        }
                    }while (serializer == null);

                    using (MemoryStream ms = new MemoryStream(message))
                    {
                        try
                        {
                            return(serializer.Deserialize(ms));
                        }
                        catch (Exception ex)
                        {
                            this.Error("Fail to deserialize message, Ingored \r\n {0} \r\n {1}", Encoding.UTF8.GetString(message), ex);

                            if (isUnprocessedMessage == false)
                            {
                                this.Write(Utils.CreateUnprocessedMessage(Encoding.UTF8.GetString(message), UnprocessedMessageReason.SyntaxError));
                            }
                            return(Read(readTimeOutSeconds));
                        }
                    }
                }
            }catch (IOException ex)
            {
                SocketException socketException = ex.InnerException as SocketException;

                if (socketException != null)
                {
                    SocketError socketError = socketException.SocketErrorCode;

                    this.Error($"Reading serialized object failed because of socket interruption. Error: { socketError.ToString() }", ex);
                }
            }catch (Exception ex)
            {
                this.Error("Reading serialized object failed.", ex);
                this.Write(Utils.CreateUnprocessedMessage(ex.Message, UnprocessedMessageReason.NotSupported));
            }

            return(null);
        }