/// <summary>
        /// Registers a content handler for a particular type of payload.
        /// </summary>
        /// <typeparam name="TPayload">The specific type of payload for this handler.</typeparam>
        /// <typeparam name="THandler">The type of the handler.</typeparam>
        /// <typeparam name="T1">The type of the first parameter.</typeparam>
        /// <typeparam name="T2">The type of the second parameter.</typeparam>
        /// <typeparam name="T3">The type of the third parameter.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="contentFactory">The service collection with which to register the handler.</param>
        /// <param name="handlerClass">The class of handler (e.g. "viewFactory", "messageDispatcher").</param>
        /// <param name="handlerFactory">A factory function to create the singleton handler.</param>
        /// <returns>The service collection.</returns>
        public static ContentFactory RegisterAsyncContentEnvelopeHandlerWithResult <TPayload, THandler, T1, T2, T3, TResult>(this ContentFactory contentFactory, string handlerClass, Func <IServiceProvider, THandler> handlerFactory)
            where THandler : class, IAsyncContentHandlerWithResult <TPayload, T1, T2, T3, TResult>
        {
            if (contentFactory is null)
            {
                throw new ArgumentNullException(nameof(contentFactory));
            }

            if (handlerClass is null)
            {
                throw new ArgumentNullException(nameof(handlerClass));
            }

            if (handlerFactory is null)
            {
                throw new ArgumentNullException(nameof(handlerFactory));
            }

            string contentType = ContentFactory.GetContentType <TPayload>();

            contentFactory.Services.AddSingleton(handlerFactory);
            contentFactory.RegisterAsyncContentHandlerWithResult <ContentEnvelope, AsyncContentEnvelopeHandlerWithResultAndClass <TPayload, THandler, T1, T2, T3, TResult>, T1, T2, T3, TResult>(contentType, handlerClass);

            return(contentFactory);
        }
        /// <summary>
        /// Registers a content handler for a particular type of payload.
        /// </summary>
        /// <typeparam name="TPayload">The specific type of payload for this handler.</typeparam>
        /// <typeparam name="T1">The type of the first parameter.</typeparam>
        /// <typeparam name="T2">The type of the second parameter.</typeparam>
        /// <typeparam name="T3">The type of the third parameter.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="contentFactory">The service collection with which to register the handler.</param>
        /// <param name="handle">The function with which to handle the payload.</param>
        /// <param name="handlerClass">The class of handler (e.g. "viewFactory", "messageDispatcher").</param>
        /// <returns>The service collection.</returns>
        public static ContentFactory RegisterAsyncContentEnvelopeHandlerWithResult <TPayload, T1, T2, T3, TResult>(this ContentFactory contentFactory, Func <TPayload, T1, T2, T3, Task <TResult> > handle, string handlerClass)
        {
            if (contentFactory is null)
            {
                throw new ArgumentNullException(nameof(contentFactory));
            }

            if (handle is null)
            {
                throw new ArgumentNullException(nameof(handle));
            }

            if (handlerClass is null)
            {
                throw new ArgumentNullException(nameof(handlerClass));
            }

            string contentType = ContentFactory.GetContentType <TPayload>();

            contentFactory.RegisterAsyncContentHandlerWithResult <ContentEnvelope, T1, T2, T3, TResult>(
                contentType,
                (envelope, param1, param2, param3) => handle(envelope.GetContents <TPayload>(), param1, param2, param3),
                handlerClass);

            return(contentFactory);
        }