File: src\Compilers\Core\Portable\InternalUtilities\ReflectionUtilities.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.ExceptionServices;
 
namespace Roslyn.Utilities
{
    internal static class ReflectionUtilities
    {
        private static readonly Type Missing = typeof(void);
 
        public static Type? TryGetType(string assemblyQualifiedName)
        {
            try
            {
                // Note that throwOnError=false only suppresses some exceptions, not all.
                return Type.GetType(assemblyQualifiedName, throwOnError: false);
            }
            catch
            {
                return null;
            }
        }
 
        public static Type? TryGetType([NotNull] ref Type? lazyType, string assemblyQualifiedName)
        {
            if (lazyType == null)
            {
                lazyType = TryGetType(assemblyQualifiedName) ?? Missing;
            }
 
            return (lazyType == Missing) ? null : lazyType;
        }
 
        /// <summary>
        /// Find a <see cref="Type"/> instance by first probing the contract name and then the name as it
        /// would exist in mscorlib.  This helps satisfy both the CoreCLR and Desktop scenarios. 
        /// </summary>
        public static Type? GetTypeFromEither(string contractName, string desktopName)
        {
            var type = TryGetType(contractName);
 
            if (type == null)
            {
                type = TryGetType(desktopName);
            }
 
            return type;
        }
 
        public static Type? GetTypeFromEither([NotNull] ref Type? lazyType, string contractName, string desktopName)
        {
            if (lazyType == null)
            {
                lazyType = GetTypeFromEither(contractName, desktopName) ?? Missing;
            }
 
            return (lazyType == Missing) ? null : lazyType;
        }
 
        public static T? FindItem<T>(IEnumerable<T> collection, params Type[] paramTypes)
            where T : MethodBase
        {
            foreach (var current in collection)
            {
                var p = current.GetParameters();
                if (p.Length != paramTypes.Length)
                {
                    continue;
                }
 
                bool allMatch = true;
                for (int i = 0; i < paramTypes.Length; i++)
                {
                    if (p[i].ParameterType != paramTypes[i])
                    {
                        allMatch = false;
                        break;
                    }
                }
 
                if (allMatch)
                {
                    return current;
                }
            }
 
            return null;
        }
 
        internal static MethodInfo? GetDeclaredMethod(this TypeInfo typeInfo, string name, params Type[] paramTypes)
        {
            return FindItem(typeInfo.GetDeclaredMethods(name), paramTypes);
        }
 
        internal static ConstructorInfo? GetDeclaredConstructor(this TypeInfo typeInfo, params Type[] paramTypes)
        {
            return FindItem(typeInfo.DeclaredConstructors, paramTypes);
        }
 
        public static T? CreateDelegate<T>(this MethodInfo? methodInfo)
            where T : Delegate
        {
            if (methodInfo == null)
            {
                return null;
            }
 
            return (T)methodInfo.CreateDelegate(typeof(T));
        }
 
        public static T? InvokeConstructor<T>(this ConstructorInfo? constructorInfo, params object?[] args)
        {
            if (constructorInfo == null)
            {
                return default;
            }
 
            try
            {
                return (T?)constructorInfo.Invoke(args);
            }
            catch (TargetInvocationException e)
            {
                Debug.Assert(e.InnerException is object);
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();
                Debug.Assert(false, "Unreachable");
                return default;
            }
        }
 
        public static object? InvokeConstructor(this ConstructorInfo constructorInfo, params object?[] args)
        {
            return constructorInfo.InvokeConstructor<object?>(args);
        }
 
        public static T? Invoke<T>(this MethodInfo methodInfo, object obj, params object?[] args)
        {
            return (T?)methodInfo.Invoke(obj, args);
        }
    }
}