/// <inheritdoc />
        /// <summary>
        /// Finds the most appropriate type or subtype of
        /// <typeparamref name="TProvider" /> whose type name is <paramref name="providerName" />
        /// or which has been decorated with a <see cref="T:Platibus.Config.Extensibility.ProviderAttribute" /> with the
        /// specified <paramref name="providerName" />.
        /// </summary>
        /// <typeparam name="TProvider">The provider type or at type from which the provider
        /// must inherit</typeparam>
        /// <param name="providerName">The provider name associated with the type</param>
        /// <returns>Returns a new provider instance with the specified
        /// <paramref name="providerName" /> and type.</returns>
        /// <exception cref="T:System.NullReferenceException">Thrown if <paramref name="providerName" />
        /// is <c>null</c> or whitespace.</exception>
        /// <exception cref="T:Platibus.Config.Extensibility.ProviderNotFoundException">Thrown if no suitable providers are
        /// found in the application domain.</exception>
        /// <exception cref="T:Platibus.Config.Extensibility.MultipleProvidersFoundException">Thrown if there are multiple
        /// providers found with the same priority.</exception>
        /// <seealso cref="T:Platibus.Config.Extensibility.ProviderAttribute" />
        public TProvider GetProvider <TProvider>(string providerName)
        {
            var providerType = Type.GetType(providerName);

            if (providerType == null)
            {
                var prioritizedProviders = _reflectionService
                                           .FindConcreteSubtypes <TProvider>()
                                           .Where(t => !t.IsGenericTypeDefinition)
                                           .WithProviderName(providerName)
                                           .GroupByPriorityDescending()
                                           .ToList();

                var highestPriority = prioritizedProviders.FirstOrDefault();
                if (highestPriority == null)
                {
                    throw new ProviderNotFoundException(providerName);
                }

                var providers = highestPriority.ToList();
                if (providers.Count > 1)
                {
                    throw new MultipleProvidersFoundException(providerName, providers);
                }

                providerType = providers.First();
            }

            return((TProvider)Activator.CreateInstance(providerType));
        }