/// <summary>
        /// Method is called when a response is received from the duplex output channel.
        /// It wrapps the response and sends the wrapped response to the correct response receiver as the response.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnResponseMessageReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                try
                {
                    // try to find the response receiver id where the wrapped message should be responded.
                    TDuplexConnection aConnction = null;
                    using (ThreadLock.Lock(myConnections))
                    {
                        aConnction = myConnections.FirstOrDefault(x => x.DuplexOutputChannel == (IDuplexOutputChannel)sender);
                    }

                    if (aConnction != null)
                    {
                        ISerializer aSerializer = mySerializer.ForResponseReceiver(aConnction.ResponseReceiverId);

                        object aMessage = DataWrapper.Wrap(e.ChannelId, e.Message, aSerializer);
                        AttachedDuplexInputChannel.SendResponseMessage(aConnction.ResponseReceiverId, aMessage);
                    }
                    else
                    {
                        EneterTrace.Warning(TracedObject + "failed to send the response message because the response receiver id does not exist. It is possible the response receiver has already been disconnected.");
                    }
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + ErrorHandler.FailedToSendResponseMessage, err);
                }
            }
        }
        public string GetAssociatedResponseReceiverId(string responseReceiverId)
        {
            using (EneterTrace.Entering())
            {
                using (ThreadLock.Lock(myConnections))
                {
                    TDuplexConnection aConnection = myConnections.FirstOrDefault(x => x.DuplexOutputChannel.ResponseReceiverId == responseReceiverId);
                    if (aConnection != null)
                    {
                        return(aConnection.ResponseReceiverId);
                    }

                    return(null);
                }
            }
        }
        protected override void OnRequestMessageReceived(object sender, DuplexChannelMessageEventArgs e)
        {
            using (EneterTrace.Entering())
            {
                WrappedData aWrappedData = null;

                try
                {
                    ISerializer aSerializer = mySerializer.ForResponseReceiver(e.ResponseReceiverId);

                    // Unwrap the incoming message.
                    aWrappedData = DataWrapper.Unwrap(e.Message, aSerializer);
                }
                catch (Exception err)
                {
                    EneterTrace.Error(TracedObject + "failed to unwrap the message.", err);
                    return;
                }

                // WrappedData.AddedData represents the channel id.
                // Therefore if everything is ok then it must be string.
                if (aWrappedData.AddedData is string)
                {
                    string aMessageReceiverId = (string)aWrappedData.AddedData;

                    TDuplexConnection aConectionToOutput = null;

                    // Try to find if the output channel with the required channel id and for the incoming response receiver
                    // already exists.
                    using (ThreadLock.Lock(myConnections))
                    {
                        aConectionToOutput = myConnections.FirstOrDefault(x => x.DuplexOutputChannel.ChannelId == aMessageReceiverId && x.ResponseReceiverId == e.ResponseReceiverId);

                        // If it does not exist then create the duplex output channel and open connection.
                        if (aConectionToOutput == null)
                        {
                            IDuplexOutputChannel aDuplexOutputChannel = null;

                            try
                            {
                                aDuplexOutputChannel = myOutputMessagingFactory.CreateDuplexOutputChannel(aMessageReceiverId);
                                aDuplexOutputChannel.ResponseMessageReceived += OnResponseMessageReceived;
                                aDuplexOutputChannel.OpenConnection();
                            }
                            catch (Exception err)
                            {
                                EneterTrace.Error(TracedObject + "failed to create and connect the duplex output channel '" + aMessageReceiverId + "'", err);

                                if (aDuplexOutputChannel != null)
                                {
                                    aDuplexOutputChannel.ResponseMessageReceived -= OnResponseMessageReceived;
                                    aDuplexOutputChannel.CloseConnection();
                                    aDuplexOutputChannel = null;
                                }
                            }

                            if (aDuplexOutputChannel != null)
                            {
                                aConectionToOutput = new TDuplexConnection(e.ResponseReceiverId, aDuplexOutputChannel);
                                myConnections.Add(aConectionToOutput);
                            }
                        }
                    }

                    if (aConectionToOutput != null)
                    {
                        try
                        {
                            // Send the unwrapped message.
                            aConectionToOutput.DuplexOutputChannel.SendMessage(aWrappedData.OriginalData);
                        }
                        catch (Exception err)
                        {
                            EneterTrace.Error(TracedObject + "failed to send the message to the output channel '" + aConectionToOutput.DuplexOutputChannel.ChannelId + "'.", err);
                        }
                    }
                }
                else
                {
                    EneterTrace.Error(TracedObject + "detected that the unwrapped message contian the channel id as the string type.");
                }
            }
        }