/// <summary>
        /// Registers a delegate that will be used to configure a named <see cref="IDeliveryClient"/> via <see cref="IDeliveryClientFactory"/>
        /// </summary>
        /// <param name="services">A <see cref="ServiceCollection"/> instance for registering and resolving dependencies.</param>
        /// <param name="name">The name of the client configuration</param>
        /// <param name="configuration">A set of key/value application configuration properties.</param>
        /// <param name="configurationSectionName">The section name of the configuration that keeps the <see cref="DeliveryOptions"/> properties. The default value is DeliveryOptions.</param>
        /// <param name="namedServiceProviderType">A named service provider type.</param>
        /// <returns>The <paramref name="services"/> instance with <see cref="IDeliveryClient"/> registered in it</returns>
        public static IServiceCollection AddDeliveryClient(this IServiceCollection services, string name, IConfiguration configuration, string configurationSectionName = "DeliveryOptions", NamedServiceProviderType namedServiceProviderType = NamedServiceProviderType.None)
        {
            var options = new DeliveryOptions();

            configuration.GetSection(configurationSectionName).Bind(options);
            options.Name = name;

            return(services
                   .RegisterOptions(options, name)
                   .RegisterDependencies(true)
                   .RegisterNamedServices(namedServiceProviderType));
        }
        /// <summary>
        /// Registers a delegate that will be used to configure a named <see cref="IDeliveryClient"/> via <see cref="IDeliveryClientFactory"/>
        /// </summary>
        ///<param name="name">The name of the client configuration</param>
        /// <param name="services">A <see cref="ServiceCollection"/> instance for registering and resolving dependencies.</param>
        /// <param name="buildDeliveryOptions">A function that is provided with an instance of <see cref="DeliveryOptionsBuilder"/>and expected to return a valid instance of <see cref="DeliveryOptions"/>.</param>
        /// <param name="namedServiceProviderType">A named service provider type.</param>
        /// <returns>The <paramref name="services"/> instance with <see cref="IDeliveryClient"/> registered in it</returns>
        public static IServiceCollection AddDeliveryClient(this IServiceCollection services, string name, Func <IDeliveryOptionsBuilder, DeliveryOptions> buildDeliveryOptions, NamedServiceProviderType namedServiceProviderType = NamedServiceProviderType.None)
        {
            if (buildDeliveryOptions == null)
            {
                throw new ArgumentNullException(nameof(buildDeliveryOptions), "The function for creating Delivery options is null.");
            }

            var options = DeliveryOptionsHelpers.Build(buildDeliveryOptions);

            options.Name = name;

            return(services
                   .RegisterOptions(options, name)
                   .RegisterDependencies(true)
                   .RegisterNamedServices(namedServiceProviderType));
        }
        /// <summary>
        /// Registers a delegate that will be used to configure a named <see cref="IDeliveryClient"/> via <see cref="IDeliveryClientFactory"/>
        /// </summary>
        ///<param name="name">The name of the client configuration</param>
        /// <param name="services">A <see cref="ServiceCollection"/> instance for registering and resolving dependencies.</param>
        /// <param name="deliveryOptions">A <see cref="DeliveryOptions"/> instance.  Options themselves are not further validated (see <see cref="DeliveryOptionsValidator.Validate"/>).</param>
        /// <param name="namedServiceProviderType">A named service provider type.</param>
        /// <returns>The <paramref name="services"/> instance with <see cref="IDeliveryClient"/> registered in it</returns>
        public static IServiceCollection AddDeliveryClient(this IServiceCollection services, string name, DeliveryOptions deliveryOptions, NamedServiceProviderType namedServiceProviderType = NamedServiceProviderType.None)
        {
            if (deliveryOptions == null)
            {
                throw new ArgumentNullException(nameof(deliveryOptions), "The Delivery options object is not specified.");
            }

            deliveryOptions.Name = name;

            return(services
                   .RegisterOptions(deliveryOptions, name)
                   .RegisterDependencies(true)
                   .RegisterNamedServices(namedServiceProviderType));
        }
        private static IServiceCollection RegisterNamedServices(this IServiceCollection services, NamedServiceProviderType namedServiceProviderType)
        {
            if (namedServiceProviderType == NamedServiceProviderType.Autofac)
            {
                services.TryAddSingleton <INamedServiceProvider, AutofacServiceProvider>();
            }

            services.AddSingleton <IDeliveryClientFactory, NamedDeliveryClientFactory>();

            return(services);
        }