File: Microsoft\Internal\ReflectionServices.cs
Web Access
Project: src\src\libraries\System.ComponentModel.Composition\src\System.ComponentModel.Composition.csproj (System.ComponentModel.Composition)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
 
namespace Microsoft.Internal
{
    internal static class ReflectionServices
    {
        public static Assembly Assembly(this MemberInfo member)
        {
            if (member is Type type)
            {
                return type.Assembly;
            }
 
            Debug.Assert(member.DeclaringType != null);
            return member.DeclaringType.Assembly;
        }
 
        public static bool IsVisible(this ConstructorInfo constructor)
        {
            return constructor.DeclaringType!.IsVisible && constructor.IsPublic;
        }
 
        public static bool IsVisible(this FieldInfo field)
        {
            Debug.Assert(field.DeclaringType != null);
            return field.DeclaringType.IsVisible && field.IsPublic;
        }
 
        public static bool IsVisible(this MethodInfo method)
        {
            Debug.Assert(method.DeclaringType != null);
            if (!method.DeclaringType.IsVisible)
                return false;
 
            if (!method.IsPublic)
                return false;
 
            if (method.IsGenericMethod)
            {
                // Check type arguments, for example if we're passed 'Activator.CreateInstance<SomeMefInternalType>()'
                foreach (Type typeArgument in method.GetGenericArguments())
                {
                    if (!typeArgument.IsVisible)
                        return false;
                }
            }
 
            return true;
        }
 
        public static string GetDisplayName(Type declaringType, string? name)
        {
            ArgumentNullException.ThrowIfNull(declaringType);
 
            return declaringType.GetDisplayName() + "." + name;
        }
 
        public static string GetDisplayName(this MemberInfo member)
        {
            ArgumentNullException.ThrowIfNull(member);
 
            switch (member.MemberType)
            {
                case MemberTypes.TypeInfo:
                case MemberTypes.NestedType:
 
                    return AttributedModelServices.GetTypeIdentity(((Type)member));
            }
 
            return GetDisplayName(member.DeclaringType!, member.Name);
        }
 
        internal static bool TryGetGenericInterfaceType(Type instanceType, Type targetOpenInterfaceType, [NotNullWhen(true)] out Type? targetClosedInterfaceType)
        {
            // The interface must be open
            if (!targetOpenInterfaceType.IsInterface ||
                !targetOpenInterfaceType.IsGenericTypeDefinition ||
                instanceType.IsGenericTypeDefinition)
            {
                throw new Exception(SR.Diagnostic_InternalExceptionMessage);
            }
 
            // if instanceType is an interface, we must first check it directly
            if (instanceType.IsInterface &&
                instanceType.IsGenericType &&
                instanceType.UnderlyingSystemType.GetGenericTypeDefinition() == targetOpenInterfaceType.UnderlyingSystemType)
            {
                targetClosedInterfaceType = instanceType;
                return true;
            }
 
            try
            {
                // Purposefully not using FullName here because it results in a significantly
                //  more expensive implementation of GetInterface, this does mean that we're
                //  takign the chance that there aren't too many types which implement multiple
                //  interfaces by the same name...
                Type? targetInterface = instanceType.GetInterface(targetOpenInterfaceType.Name, false);
                if (targetInterface != null &&
                    targetInterface.UnderlyingSystemType.GetGenericTypeDefinition() == targetOpenInterfaceType.UnderlyingSystemType)
                {
                    targetClosedInterfaceType = targetInterface;
                    return true;
                }
            }
            catch (AmbiguousMatchException)
            {
                // If there are multiple with the same name we should not pick any
            }
 
            targetClosedInterfaceType = null;
            return false;
        }
 
        internal static IEnumerable<PropertyInfo> GetAllProperties(this Type type)
        {
            return type.GetInterfaces().Concat(new Type[] { type }).SelectMany(itf => itf.GetProperties());
        }
 
        internal static IEnumerable<MethodInfo> GetAllMethods(this Type type)
        {
            IEnumerable<MethodInfo> declaredMethods = type.GetDeclaredMethods();
 
            Type? baseType = type.BaseType;
            Debug.Assert(baseType != null);
            if (baseType.UnderlyingSystemType != typeof(object))
            {
                return declaredMethods.Concat(baseType.GetAllMethods());
            }
            else
            {
                return declaredMethods;
            }
        }
 
        private static IEnumerable<MethodInfo> GetDeclaredMethods(this Type type)
        {
            foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
            {
                yield return method;
            }
        }
 
        public static IEnumerable<FieldInfo> GetAllFields(this Type type)
        {
            IEnumerable<FieldInfo> declaredFields = type.GetDeclaredFields();
 
            Type? baseType = type.BaseType;
            Debug.Assert(baseType != null);
            if (baseType.UnderlyingSystemType != typeof(object))
            {
                return declaredFields.Concat(baseType.GetAllFields());
            }
            else
            {
                return declaredFields;
            }
        }
 
        private static IEnumerable<FieldInfo> GetDeclaredFields(this Type type)
        {
            foreach (FieldInfo m in type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
            {
                yield return m;
            }
        }
 
        internal static bool HasBaseclassOf(this Type? type, Type baseClass)
        {
            if (type == baseClass)
            {
                return false;
            }
 
            while (type != null)
            {
                if (type == baseClass)
                    return true;
                type = type.BaseType;
            }
            return false;
        }
 
    }
}