internal static object CreateReloadingProxy(this IConfiguration configuration, Type interfaceType,
                                                    DefaultTypes defaultTypes, ValueConverters valueConverters, Type declaringType, string memberName,
                                                    IResolver resolver)
        {
            if (configuration.IsNull())
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (interfaceType.IsNull())
            {
                throw new ArgumentNullException(nameof(interfaceType));
            }

            if (!interfaceType.GetTypeInfo().IsInterface)
            {
                throw new ArgumentException($"Specified type is not an interface: '{interfaceType.FullName}'.",
                                            nameof(interfaceType));
            }

            if (interfaceType == typeof(IEnumerable))
            {
                throw new ArgumentException("The IEnumerable interface is not supported.");
            }

            if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(interfaceType))
            {
                throw new ArgumentException(
                          $"Interfaces that inherit from IEnumerable are not supported: '{interfaceType.FullName}'",
                          nameof(interfaceType));
            }

            if (configuration[ConfigurationObjectFactory.TypeKey].IsNotNullOrEmpty() &&
                string.Equals(configuration[ConfigurationObjectFactory.ReloadOnChangeKey], "false",
                              StringComparison.OrdinalIgnoreCase))
            {
                return(configuration.BuildTypeSpecifiedObject(interfaceType, declaringType, memberName,
                                                              valueConverters ?? new ValueConverters(), defaultTypes ?? new DefaultTypes(), resolver));
            }

            var createReloadingProxy = ProxyFactories.GetOrAdd(interfaceType, CreateProxyTypeFactoryMethod);

            return(createReloadingProxy.Invoke(configuration, defaultTypes, valueConverters, declaringType, memberName,
                                               resolver));
        }
 /// <summary>
 /// Create an object of type <typeparamref name="TInterface"/> based on the specified configuration. The returned
 /// object delegates its functionality to a backing field that is reloaded when the configuration changes.
 /// </summary>
 /// <typeparam name="TInterface">The interface type to create.</typeparam>
 /// <param name="configuration">The configuration to create the object from.</param>
 /// <param name="defaultTypes">
 /// An object that defines the default types to be used when a type is not explicitly specified by a
 /// configuration section.
 /// </param>
 /// <param name="valueConverters">
 /// An object that defines custom converter functions that are used to convert string configuration
 /// values to a target type.
 /// </param>
 /// <returns>
 /// An object of type <typeparamref name="TInterface"/> with values set from the configuration that reloads
 /// itself when the configuration changes.
 /// </returns>
 public static TInterface CreateReloadingProxy <TInterface>(this IConfiguration configuration,
                                                            DefaultTypes defaultTypes, ValueConverters valueConverters)
 {
     return(configuration.CreateReloadingProxy <TInterface>(defaultTypes, valueConverters, null));
 }
 /// <summary>
 /// Create an object of type <paramref name="interfaceType"/> based on the specified configuration. The returned
 /// object delegates its functionality to a backing field that is reloaded when the configuration changes.
 /// </summary>
 /// <param name="configuration">The configuration to create the object from.</param>
 /// <param name="interfaceType">The interface type to create.</param>
 /// <param name="defaultTypes">
 /// An object that defines the default types to be used when a type is not explicitly specified by a
 /// configuration section.
 /// </param>
 /// <param name="valueConverters">
 /// An object that defines custom converter functions that are used to convert string configuration
 /// values to a target type.
 /// </param>
 /// <returns>
 /// An object of type <paramref name="interfaceType"/> with values set from the configuration that reloads
 /// itself when the configuration changes.
 /// </returns>
 public static object CreateReloadingProxy(this IConfiguration configuration, Type interfaceType,
                                           DefaultTypes defaultTypes, ValueConverters valueConverters)
 {
     return(configuration.CreateReloadingProxy(interfaceType, defaultTypes, valueConverters, null));
 }
 /// <summary>
 /// Create an object of type <paramref name="interfaceType"/> based on the specified configuration. The returned
 /// object delegates its functionality to a backing field that is reloaded when the configuration changes.
 /// </summary>
 /// <param name="configuration">The configuration to create the object from.</param>
 /// <param name="interfaceType">The interface type to create.</param>
 /// <param name="defaultTypes">
 /// An object that defines the default types to be used when a type is not explicitly specified by a
 /// configuration section.
 /// </param>
 /// <param name="valueConverters">
 /// An object that defines custom converter functions that are used to convert string configuration
 /// values to a target type.
 /// </param>
 /// <param name="resolver">
 /// An object that can retrieve constructor parameter values that are not found in configuration. This
 /// object is an adapter for dependency injection containers, such as Ninject, Unity, Autofac, or
 /// StructureMap. Consider using the <see cref="Resolver"/> class for this parameter, as it supports
 /// most dependency injection containers.
 /// </param>
 /// <returns>
 /// An object of type <paramref name="interfaceType"/> with values set from the configuration that reloads
 /// itself when the configuration changes.
 /// </returns>
 public static object CreateReloadingProxy(this IConfiguration configuration, Type interfaceType,
                                           DefaultTypes defaultTypes = null, ValueConverters valueConverters = null, IResolver resolver = null)
 {
     return(configuration.CreateReloadingProxy(interfaceType, defaultTypes, valueConverters, null, null,
                                               resolver ?? Resolver.Empty));
 }
 /// <summary>
 /// Create an object of type <typeparamref name="TInterface"/> based on the specified configuration. The returned
 /// object delegates its functionality to a backing field that is reloaded when the configuration changes.
 /// </summary>
 /// <typeparam name="TInterface">The interface type to create.</typeparam>
 /// <param name="configuration">The configuration to create the object from.</param>
 /// <param name="defaultTypes">
 /// An object that defines the default types to be used when a type is not explicitly specified by a
 /// configuration section.
 /// </param>
 /// <param name="valueConverters">
 /// An object that defines custom converter functions that are used to convert string configuration
 /// values to a target type.
 /// </param>
 /// <param name="resolver">
 /// An object that can retrieve constructor parameter values that are not found in configuration. This
 /// object is an adapter for dependency injection containers, such as Ninject, Unity, Autofac, or
 /// StructureMap. Consider using the <see cref="Resolver"/> class for this parameter, as it supports
 /// most dependency injection containers.
 /// </param>
 /// <returns>
 /// An object of type <typeparamref name="TInterface"/> with values set from the configuration that reloads
 /// itself when the configuration changes.
 /// </returns>
 public static TInterface CreateReloadingProxy <TInterface>(this IConfiguration configuration,
                                                            DefaultTypes defaultTypes = null, ValueConverters valueConverters = null, IResolver resolver = null)
 {
     return((TInterface)configuration.CreateReloadingProxy(typeof(TInterface), defaultTypes, valueConverters,
                                                           resolver));
 }