File: System\Configuration\TypeUtil.cs
Web Access
Project: src\src\libraries\System.Configuration.ConfigurationManager\src\System.Configuration.ConfigurationManager.csproj (System.Configuration.ConfigurationManager)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Configuration.Internal;
using System.Reflection;
 
namespace System.Configuration
{
    internal static class TypeUtil
    {
        internal const string ConfigurationManagerAssemblyName = "System.Configuration.ConfigurationManager";
 
        // Deliberately not being explicit about the versions to make
        // things simpler for consumers of System.Configuration.
        private static readonly string[] s_implicitAssemblies =
        {
            // Historically we would find types in System.dll here.
            // This is because Configuration used to live in System.dll
            // and by resolution rules, typenames without an assembly
            // specifier would be found there:
            //
            // (current executing assembly -> mscorlib / now s.p.c.l)
            //
            // When Configuration types moved to System.Configuration
            // the implicit lookup for System had to be added to keep
            // existing configuration files working.
 
            // We also need to find types in mscorlib.dll as currently
            // only types found in System.Private.CoreLib.dll are
            // implicitly resolved. If this changes we can remove the
            // explicit mscorlib lookup.
 
            "mscorlib",
            "System",
        };
 
        /// <summary>
        /// Find type references that used to be found without assembly names
        /// </summary>
        private static Type GetImplicitType(string typeString)
        {
            // Since the config APIs were originally implemented in System.dll,
            // references to types without assembly names could be resolved if
            // they lived in System.dll.
            //
            // On .NET Framework we would try to emulate that behavior by looking in
            // System. As types have moved around in .NET Core, we'll try to load
            // from the a variety of assemblies to mimick the old behavior.
 
            // Don't bother to look around if we've already got something that
            // is clearly not a simple type name.
            if (string.IsNullOrEmpty(typeString) || typeString.IndexOf(',') != -1) // string.Contains(char) is .NetCore2.1+ specific
                return null;
 
            // Ignore all exceptions, otherwise callers will get unexpected
            // exceptions not related to the original failure to load the
            // desired type.
 
            // First attempt is against our own System.Configuration types
            try
            {
                Assembly configurationAssembly = typeof(ConfigurationException).Assembly;
                Type type = configurationAssembly.GetType(typeString, false);
                if (type != null)
                    return type;
            }
            catch { }
 
            foreach (string assembly in s_implicitAssemblies)
            {
                try
                {
                    Type type = Type.GetType($"{typeString}, {assembly}");
                    if (type != null)
                        return type;
                }
                catch { }
            }
 
            return null;
        }
 
        // Get the type specified by typeString. If it fails, try to retrieve it
        // as a type from System.dll. If that fails,  return null or throw the original
        // exception as indicated by throwOnError.
        internal static Type GetType(string typeString, bool throwOnError)
        {
            Type type;
 
            try
            {
                type = Type.GetType(typeString, throwOnError);
            }
            catch
            {
                type = GetImplicitType(typeString);
                if (type == null)
                {
                    throw;
                }
            }
 
            return type ?? GetImplicitType(typeString);
        }
 
        // Ask the host to get the type specified by typeString. If it fails, try to retrieve it
        // as a type from System.dll. If that fails, return null or throw the original
        // exception as indicated by throwOnError.
        internal static Type GetType(IInternalConfigHost host, string typeString, bool throwOnError)
        {
            Type type;
            try
            {
                type = host.GetConfigType(typeString, throwOnError);
            }
            catch
            {
                type = GetImplicitType(typeString);
                if (type == null)
                {
                    throw;
                }
            }
 
            return type ?? GetImplicitType(typeString);
        }
 
        internal static T CreateInstance<T>(string typeString)
        {
            Type type = GetType(typeString, true);
            VerifyAssignableType(typeof(T), type, true);
            return (T)Activator.CreateInstance(type, true);
        }
 
        internal static object CreateInstance(Type type)
        {
            return Activator.CreateInstance(type, true);
        }
 
        internal static ConstructorInfo GetConstructor(Type type, Type baseType, bool throwOnError)
        {
            type = VerifyAssignableType(baseType, type, throwOnError);
            if (type == null)
                return null;
 
            const BindingFlags BindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
 
            ConstructorInfo ctor = type.GetConstructor(BindingFlags, null, CallingConventions.HasThis, Type.EmptyTypes,
                null);
            if ((ctor == null) && throwOnError)
                throw new TypeLoadException(SR.Format(SR.TypeNotPublic, type.AssemblyQualifiedName));
 
            return ctor;
        }
 
        internal static Type VerifyAssignableType(Type baseType, Type type, bool throwOnError)
        {
            if (baseType.IsAssignableFrom(type))
                return type;
 
            if (throwOnError)
            {
                throw new TypeLoadException(
                    SR.Format(SR.Config_type_doesnt_inherit_from_type, type.FullName, baseType.FullName));
            }
 
            return null;
        }
    }
}