/// <summary>
 ///		Process request message before serialization.
 /// </summary>
 /// <param name="context">Context information of serializing message.</param>
 protected abstract void ProcessCore( RequestMessageSerializationContext context );
        private static void SerializeCore( RpcOutputBuffer buffer, int? messageId, RequestMessageSerializationContext context )
        {
            using ( var stream = buffer.OpenWriteStream() )
            using ( var packer = Packer.Create( stream ) )
            {
                packer.PackArrayHeader( messageId == null ? 3 : 4 );
                packer.Pack( ( int )( messageId == null ? MessageType.Notification : MessageType.Request ) );

                if ( messageId != null )
                {
                    packer.Pack( unchecked( ( uint )messageId.Value ) );
                }

                packer.PackString( context.MethodName );
                packer.PackItems( context.Arguments );
            }
        }
        /// <summary>
        ///		Process request message before serialization.
        /// </summary>
        /// <param name="context">Context information of serializing message.</param>
        internal void Process( RequestMessageSerializationContext context )
        {
            Contract.Assert( context != null );

            this.ProcessCore( context );
        }
        /// <summary>
        ///		Serialize RPC call to specified buffer.
        /// </summary>
        /// <param name="messageId">ID of message. If message is notification message, specify null.</param>
        /// <param name="method">Method name to be called.</param>
        /// <param name="arguments">Arguments of method call.</param>
        /// <param name="buffer">Buffer to be set serialized stream.</param>
        /// <returns>Error message of serialization.</returns>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="method"/>, <paramref name="arguments"/>, or <paramref name="buffer"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///		<paramref name="method"/> is illegal.
        /// </exception>
        public RpcErrorMessage Serialize( int? messageId, string method, IList<object> arguments, RpcOutputBuffer buffer )
        {
            if ( method == null )
            {
                throw new ArgumentNullException( "method" );
            }

            // TODO: more strict validation.
            if ( String.IsNullOrWhiteSpace( method ) )
            {
                throw new ArgumentException( "'method' must not be empty nor blank.", "method" );
            }

            if ( arguments == null )
            {
                throw new ArgumentNullException( "arguments" );
            }

            if ( buffer == null )
            {
                throw new ArgumentNullException( "buffer" );
            }

            Contract.EndContractBlock();

            var context = new RequestMessageSerializationContext( buffer, messageId, method, arguments );

            foreach ( var preSerializationFilter in this._preSerializationFilters )
            {
                preSerializationFilter.GetFilter().Process( context );
                if ( !context.SerializationError.IsSuccess )
                {
                    return context.SerializationError;
                }
            }

            SerializeCore( buffer, messageId, context );
            if ( !context.SerializationError.IsSuccess )
            {
                return context.SerializationError;
            }

            foreach ( var postSerializationFilter in this._postSerializationFilters )
            {
                using ( var swapper = buffer.CreateSwapper() )
                {
                    swapper.WriteBytes( postSerializationFilter.GetFilter().Process( swapper.ReadBytes(), context ) );
                    if ( !context.SerializationError.IsSuccess )
                    {
                        return context.SerializationError;
                    }
                }
            }

            return RpcErrorMessage.Success;
        }