/// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="recipient">The intended or actual recipient of the request message.</param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        IDirectedProtocolMessage IMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary <string, string> fields)
        {
            Requires.NotNull(recipient, "recipient");
            Requires.NotNull(fields, "fields");

            throw new NotImplementedException();
        }
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="recipient">The intended or actual recipient of the request message.</param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        public virtual IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary <string, string> fields)
        {
            MessageDescription matchingType = this.GetMessageDescription(recipient, fields);

            if (matchingType != null)
            {
                return(this.InstantiateAsRequest(matchingType, recipient));
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Gets the message type that best fits the given incoming request data.
        /// </summary>
        /// <param name="recipient">The recipient of the incoming data.  Typically not used, but included just in case.</param>
        /// <param name="fields">The data of the incoming message.</param>
        /// <returns>
        /// The message type that matches the incoming data; or <c>null</c> if no match.
        /// </returns>
        /// <exception cref="ProtocolException">May be thrown if the incoming data is ambiguous.</exception>
        protected virtual MessageDescription GetMessageDescription(MessageReceivingEndpoint recipient, IDictionary <string, string> fields)
        {
            Requires.NotNull(recipient, "recipient");
            Requires.NotNull(fields, "fields");

            var matches = this.requestMessageTypes.Keys
                          .Where(message => message.CheckMessagePartsPassBasicValidation(fields))
                          .OrderByDescending(message => CountInCommon(message.Mapping.Keys, fields.Keys))
                          .ThenByDescending(message => message.Mapping.Count)
                          .CacheGeneratedResults();
            var match = matches.FirstOrDefault();

            if (match != null)
            {
                return(match);
            }
            else
            {
                // No message type matches the incoming data.
                return(null);
            }
        }
        /// <summary>
        /// Instantiates the given request message type.
        /// </summary>
        /// <param name="messageDescription">The message description.</param>
        /// <param name="recipient">The recipient.</param>
        /// <returns>The instantiated message.  Never null.</returns>
        protected virtual IDirectedProtocolMessage InstantiateAsRequest(MessageDescription messageDescription, MessageReceivingEndpoint recipient)
        {
            Requires.NotNull(messageDescription, "messageDescription");
            Requires.NotNull(recipient, "recipient");
            Contract.Ensures(Contract.Result <IDirectedProtocolMessage>() != null);

            ConstructorInfo ctor = this.requestMessageTypes[messageDescription];

            return((IDirectedProtocolMessage)ctor.Invoke(new object[] { recipient.Location, messageDescription.MessageVersion }));
        }