public static bool IsSubclassOf(this TypeReference type, string ns, string name, ITryResolveMetadata resolver)
        {
            TypeDefinition baseType = resolver.TryResolve(type);

            while (baseType != null)
            {
                if (baseType.IsTypeOf(ns, name))
                {
                    return(true);
                }
                baseType = resolver.TryResolve(baseType.BaseType);
            }

            return(false);
        }
        public static IEnumerable <(TypeReference InflatedInterface, InterfaceImplementation OriginalImpl)> GetInflatedInterfaces(this TypeReference typeRef, ITryResolveMetadata resolver)
        {
            var typeDef = resolver.TryResolve(typeRef);

            if (typeDef?.HasInterfaces != true)
            {
                yield break;
            }

            if (typeRef is GenericInstanceType genericInstance)
            {
                foreach (var interfaceImpl in typeDef.Interfaces)
                {
                    // InflateGenericType only returns null when inflating generic parameters (and the generic instance type doesn't resolve).
                    // Here we are not inflating a generic parameter but an interface type reference.
                    yield return((InflateGenericType(genericInstance, interfaceImpl.InterfaceType, resolver), interfaceImpl) !);
                }
            }
            else
            {
                foreach (var interfaceImpl in typeDef.Interfaces)
                {
                    yield return(interfaceImpl.InterfaceType, interfaceImpl);
                }
            }
        }
        public static TypeDefinition ResolveType(this ModuleDefinition module, string typeFullName, ITryResolveMetadata resolver)
        {
            if (typeFullName == null)
            {
                return(null);
            }

            var type = module.GetType(typeFullName);

            if (type != null)
            {
                return(type);
            }

            if (!module.HasExportedTypes)
            {
                return(null);
            }

            // When resolving a forwarded type from a string, typeFullName should be a simple type name.
            int idx = typeFullName.LastIndexOf('.');

            (string typeNamespace, string typeName) = idx > 0 ? (typeFullName.Substring(0, idx), typeFullName.Substring(idx + 1)) :
                                                      (string.Empty, typeFullName);

            TypeReference typeReference = new TypeReference(typeNamespace, typeName, module, module);

            return(resolver.TryResolve(typeReference));
        }
        public static TypeReference GetInflatedDeclaringType(this TypeReference type, ITryResolveMetadata resolver)
        {
            if (type == null)
            {
                return(null);
            }

            if (type.IsGenericParameter || type.IsByReference || type.IsPointer)
            {
                return(null);
            }

            if (type is SentinelType sentinelType)
            {
                return(sentinelType.ElementType.GetInflatedDeclaringType(resolver));
            }

            if (type is PinnedType pinnedType)
            {
                return(pinnedType.ElementType.GetInflatedDeclaringType(resolver));
            }

            if (type is RequiredModifierType requiredModifierType)
            {
                return(requiredModifierType.ElementType.GetInflatedDeclaringType(resolver));
            }

            if (type is GenericInstanceType genericInstance)
            {
                var declaringType = genericInstance.DeclaringType;

                if (declaringType.HasGenericParameters)
                {
                    var result = new GenericInstanceType(declaringType);
                    for (var i = 0; i < declaringType.GenericParameters.Count; ++i)
                    {
                        result.GenericArguments.Add(genericInstance.GenericArguments[i]);
                    }

                    return(result);
                }

                return(declaringType);
            }

            var resolved = resolver.TryResolve(type);

            System.Diagnostics.Debug.Assert(resolved == type);
            return(resolved?.DeclaringType);
        }
        public static IEnumerable <MethodReference> GetMethods(this TypeReference type, ITryResolveMetadata resolver)
        {
            TypeDefinition typeDef = resolver.TryResolve(type);

            if (typeDef?.HasMethods != true)
            {
                yield break;
            }

            if (type is GenericInstanceType genericInstanceType)
            {
                foreach (var methodDef in typeDef.Methods)
                {
                    yield return(MakeMethodReferenceForGenericInstanceType(genericInstanceType, methodDef));
                }
            }
            else
            {
                foreach (var method in typeDef.Methods)
                {
                    yield return(method);
                }
            }
        }
        public static IEnumerable <(TypeReference InflatedInterface, InterfaceImplementation OriginalImpl)> GetInflatedInterfaces(this TypeReference typeRef, ITryResolveMetadata resolver)
        {
            var typeDef = resolver.TryResolve(typeRef);

            if (typeDef?.HasInterfaces != true)
            {
                yield break;
            }

            if (typeRef is GenericInstanceType genericInstance)
            {
                foreach (var interfaceImpl in typeDef.Interfaces)
                {
                    yield return(InflateGenericType(genericInstance, interfaceImpl.InterfaceType, resolver), interfaceImpl);
                }
            }
            else
            {
                foreach (var interfaceImpl in typeDef.Interfaces)
                {
                    yield return(interfaceImpl.InterfaceType, interfaceImpl);
                }
            }
        }
        public static TypeReference InflateGenericType(GenericInstanceType genericInstanceProvider, TypeReference typeToInflate, ITryResolveMetadata resolver)
        {
            if (typeToInflate is ArrayType arrayType)
            {
                var inflatedElementType = InflateGenericType(genericInstanceProvider, arrayType.ElementType, resolver);

                if (inflatedElementType != arrayType.ElementType)
                {
                    return(new ArrayType(inflatedElementType, arrayType.Rank));
                }

                return(arrayType);
            }

            if (typeToInflate is GenericInstanceType genericInst)
            {
                return(MakeGenericType(genericInstanceProvider, genericInst, resolver));
            }

            if (typeToInflate is GenericParameter genericParameter)
            {
                if (genericParameter.Owner is MethodReference)
                {
                    return(genericParameter);
                }

                var elementType = resolver.TryResolve(genericInstanceProvider.ElementType);
                if (elementType == null)
                {
                    return(null);
                }
                var parameter = elementType.GenericParameters.Single(p => p == genericParameter);
                return(genericInstanceProvider.GenericArguments[parameter.Position]);
            }

            if (typeToInflate is FunctionPointerType functionPointerType)
            {
                var result = new FunctionPointerType {
                    ReturnType = InflateGenericType(genericInstanceProvider, functionPointerType.ReturnType, resolver)
                };

                for (int i = 0; i < functionPointerType.Parameters.Count; i++)
                {
                    var inflatedParameterType = InflateGenericType(genericInstanceProvider, functionPointerType.Parameters[i].ParameterType, resolver);
                    result.Parameters.Add(new ParameterDefinition(inflatedParameterType));
                }

                return(result);
            }

            if (typeToInflate is IModifierType modifierType)
            {
                var modifier    = InflateGenericType(genericInstanceProvider, modifierType.ModifierType, resolver);
                var elementType = InflateGenericType(genericInstanceProvider, modifierType.ElementType, resolver);

                if (modifierType is OptionalModifierType)
                {
                    return(new OptionalModifierType(modifier, elementType));
                }

                return(new RequiredModifierType(modifier, elementType));
            }

            if (typeToInflate is PinnedType pinnedType)
            {
                var elementType = InflateGenericType(genericInstanceProvider, pinnedType.ElementType, resolver);

                if (elementType != pinnedType.ElementType)
                {
                    return(new PinnedType(elementType));
                }

                return(pinnedType);
            }

            if (typeToInflate is PointerType pointerType)
            {
                var elementType = InflateGenericType(genericInstanceProvider, pointerType.ElementType, resolver);

                if (elementType != pointerType.ElementType)
                {
                    return(new PointerType(elementType));
                }

                return(pointerType);
            }

            if (typeToInflate is ByReferenceType byReferenceType)
            {
                var elementType = InflateGenericType(genericInstanceProvider, byReferenceType.ElementType, resolver);

                if (elementType != byReferenceType.ElementType)
                {
                    return(new ByReferenceType(elementType));
                }

                return(byReferenceType);
            }

            if (typeToInflate is SentinelType sentinelType)
            {
                var elementType = InflateGenericType(genericInstanceProvider, sentinelType.ElementType, resolver);

                if (elementType != sentinelType.ElementType)
                {
                    return(new SentinelType(elementType));
                }

                return(sentinelType);
            }

            return(typeToInflate);
        }