Beispiel #1
0
        // declaredOnly will cause this to retrieve interfaces recursively required by the type, but doesn't necessarily
        // include interfaces required by any base types.
        public static IEnumerable <InterfaceImplementation> GetAllInterfaceImplementations(this TypeDefinition thisType, LinkContext context, bool declaredOnly)
        {
            TypeDefinition?type = thisType;

            while (type != null)
            {
                foreach (var i in type.Interfaces)
                {
                    yield return(i);

                    TypeDefinition?interfaceType = context.TryResolve(i.InterfaceType);
                    if (interfaceType != null)
                    {
                        // declaredOnly here doesn't matter since interfaces don't have base types
                        foreach (var innerInterface in interfaceType.GetAllInterfaceImplementations(context, declaredOnly: true))
                        {
                            yield return(innerInterface);
                        }
                    }
                }

                if (declaredOnly)
                {
                    yield break;
                }

                type = context.TryResolve(type.BaseType);
            }
        }
Beispiel #2
0
        public static IEnumerable <FieldDefinition> GetFieldsOnTypeHierarchy(this TypeDefinition thisType, LinkContext context, Func <FieldDefinition, bool>?filter, BindingFlags?bindingFlags = BindingFlags.Default)
        {
            TypeDefinition?type       = thisType;
            bool           onBaseType = false;

            while (type != null)
            {
                foreach (var field in type.Fields)
                {
                    // Ignore private fields on a base type - those are completely ignored by reflection
                    // (anything private on the base type is not visible via the derived type)
                    if (onBaseType && field.IsPrivate)
                    {
                        continue;
                    }

                    // Note that compiler generated fields backing some properties and events will get through here.
                    // This is intentional as reflection treats these as fields as well.

                    if (filter != null && !filter(field))
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Static && !field.IsStatic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Instance && field.IsStatic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public && !field.IsPublic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic && field.IsPublic)
                    {
                        continue;
                    }

                    yield return(field);
                }

                if ((bindingFlags & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly)
                {
                    yield break;
                }

                type       = context.TryResolve(type.BaseType);
                onBaseType = true;
            }
        }
Beispiel #3
0
        public static IEnumerable <MethodDefinition> GetMethodsOnTypeHierarchy(this TypeDefinition type, LinkContext context, Func <MethodDefinition, bool> filter, BindingFlags?bindingFlags = null)
        {
            bool onBaseType = false;

            while (type != null)
            {
                foreach (var method in type.Methods)
                {
                    // Ignore constructors as those are not considered methods from a reflection's point of view
                    if (method.IsConstructor)
                    {
                        continue;
                    }

                    // Ignore private methods on a base type - those are completely ignored by reflection
                    // (anything private on the base type is not visible via the derived type)
                    if (onBaseType && method.IsPrivate)
                    {
                        continue;
                    }

                    // Note that special methods like property getter/setter, event adder/remover will still get through and will be marked.
                    // This is intentional as reflection treats these as methods as well.

                    if (filter != null && !filter(method))
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Static && !method.IsStatic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Instance && method.IsStatic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public && !method.IsPublic)
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic && method.IsPublic)
                    {
                        continue;
                    }

                    yield return(method);
                }

                type       = context.TryResolve(type.BaseType);
                onBaseType = true;
            }
        }
Beispiel #4
0
        TypeReference ResolveTypeName(AssemblyDefinition assembly, TypeName typeName)
        {
            if (typeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName)
            {
                // In this case we ignore the assembly parameter since the type name has assembly in it
                var assemblyFromName = _context.TryResolve(assemblyQualifiedTypeName.AssemblyName.Name);
                return(ResolveTypeName(assemblyFromName, assemblyQualifiedTypeName.TypeName));
            }

            if (assembly == null || typeName == null)
            {
                return(null);
            }

            if (typeName is ConstructedGenericTypeName constructedGenericTypeName)
            {
                var genericTypeRef = ResolveTypeName(assembly, constructedGenericTypeName.GenericType);
                if (genericTypeRef == null)
                {
                    return(null);
                }

                TypeDefinition genericType         = genericTypeRef.Resolve();
                var            genericInstanceType = new GenericInstanceType(genericType);
                foreach (var arg in constructedGenericTypeName.GenericArguments)
                {
                    var genericArgument = ResolveTypeName(assembly, arg);
                    if (genericArgument == null)
                    {
                        return(null);
                    }

                    genericInstanceType.GenericArguments.Add(genericArgument);
                }

                return(genericInstanceType);
            }
            else if (typeName is HasElementTypeName elementTypeName)
            {
                var elementType = ResolveTypeName(assembly, elementTypeName.ElementTypeName);
                if (elementType == null)
                {
                    return(null);
                }

                return(typeName switch
                {
                    ArrayTypeName _ => new ArrayType(elementType),
                    MultiDimArrayTypeName multiDimArrayTypeName => new ArrayType(elementType, multiDimArrayTypeName.Rank),
                    ByRefTypeName _ => new ByReferenceType(elementType),
                    PointerTypeName _ => new PointerType(elementType),
                    _ => elementType
                });
Beispiel #5
0
        public static IEnumerable <InterfaceImplementation> GetAllInterfaceImplementations(this TypeDefinition type, LinkContext context)
        {
            while (type != null)
            {
                foreach (var i in type.Interfaces)
                {
                    yield return(i);

                    TypeDefinition interfaceType = context.TryResolve(i.InterfaceType);
                    if (interfaceType != null)
                    {
                        foreach (var innerInterface in interfaceType.GetAllInterfaceImplementations(context))
                        {
                            yield return(innerInterface);
                        }
                    }
                }

                type = context.TryResolve(type.BaseType);
            }
        }
Beispiel #6
0
        public IEnumerable <(InterfaceImplementation, TypeDefinition)>?GetReferencedInterfaces(MethodBody body)
        {
            var possibleStackTypes = AllPossibleStackTypes(body.Method);

            if (possibleStackTypes.Count == 0)
            {
                return(null);
            }

            var interfaceTypes = possibleStackTypes.Where(t => t.IsInterface).ToArray();

            if (interfaceTypes.Length == 0)
            {
                return(null);
            }

            var interfaceImplementations = new HashSet <(InterfaceImplementation, TypeDefinition)> ();

            // If a type could be on the stack in the body and an interface it implements could be on the stack on the body
            // then we need to mark that interface implementation.  When this occurs it is not safe to remove the interface implementation from the type
            // even if the type is never instantiated
            foreach (var type in possibleStackTypes)
            {
                // We only sweep interfaces on classes so that's why we only care about classes
                if (!type.IsClass)
                {
                    continue;
                }

                TypeDefinition?currentType = type;
                while (currentType?.BaseType != null)                 // Checking BaseType != null to skip System.Object
                {
                    AddMatchingInterfaces(interfaceImplementations, currentType, interfaceTypes);
                    currentType = context.TryResolve(currentType.BaseType);
                }
            }

            return(interfaceImplementations);
        }
Beispiel #7
0
        private HierarchyFlags GetFlags(TypeDefinition resolvedType)
        {
            if (_cache.TryGetValue(resolvedType, out var flags))
            {
                return(flags);
            }

            if (resolvedType.Name == "IReflect" && resolvedType.Namespace == "System.Reflection")
            {
                flags |= HierarchyFlags.IsSystemReflectionIReflect;
            }

            TypeDefinition?baseType = resolvedType;

            while (baseType != null)
            {
                if (baseType.IsTypeOf(WellKnownType.System_Type))
                {
                    flags |= HierarchyFlags.IsSystemType;
                }

                if (baseType.HasInterfaces)
                {
                    foreach (var iface in baseType.Interfaces)
                    {
                        if (iface.InterfaceType.Name == "IReflect" && iface.InterfaceType.Namespace == "System.Reflection")
                        {
                            flags |= HierarchyFlags.IsSystemReflectionIReflect;
                        }
                    }
                }

                baseType = context.TryResolve(baseType.BaseType);
            }

            if (resolvedType != null)
            {
                _cache.Add(resolvedType, flags);
            }

            return(flags);
        }
Beispiel #8
0
        public static TypeDefinition FindPredefinedType(string ns, string name, LinkContext context)
        {
            foreach (var corlibName in corlibNames)
            {
                AssemblyDefinition corlib = context.TryResolve(corlibName);
                if (corlib == null)
                {
                    continue;
                }

                TypeDefinition type = corlib.MainModule.GetType(ns, name);
                // The assembly could be a facade with type forwarders, in which case we don't find the type in this assembly.
                if (type != null)
                {
                    return(type);
                }
            }

            return(null);
        }
Beispiel #9
0
        public static TypeDefinition?FindPredefinedType(WellKnownType type, LinkContext context)
        {
            var(ns, name) = type.GetNamespaceAndName();
            foreach (var corlibName in corlibNames)
            {
                AssemblyDefinition?corlib = context.TryResolve(corlibName);
                if (corlib == null)
                {
                    continue;
                }

                TypeDefinition resolvedType = corlib.MainModule.GetType(ns, name);
                // The assembly could be a facade with type forwarders, in which case we don't find the type in this assembly.
                if (resolvedType != null)
                {
                    return(resolvedType);
                }
            }

            return(null);
        }
Beispiel #10
0
        public bool TryResolveTypeName(string typeNameString, ICustomAttributeProvider?origin, [NotNullWhen(true)] out TypeReference?typeReference, [NotNullWhen(true)] out AssemblyDefinition?typeAssembly, bool needsAssemblyName = true)
        {
            typeReference = null;
            typeAssembly  = null;
            if (string.IsNullOrEmpty(typeNameString))
            {
                return(false);
            }

            TypeName parsedTypeName;

            try {
                parsedTypeName = TypeParser.ParseTypeName(typeNameString);
            } catch (ArgumentException) {
                return(false);
            } catch (System.IO.FileLoadException) {
                return(false);
            }

            if (parsedTypeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName)
            {
                typeAssembly = _context.TryResolve(assemblyQualifiedTypeName.AssemblyName.Name);
                if (typeAssembly == null)
                {
                    return(false);
                }

                typeReference = ResolveTypeName(typeAssembly, assemblyQualifiedTypeName.TypeName);
                return(typeReference != null);
            }

            // If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
            // search for the type in the calling object's assembly. If not found, look in the core
            // assembly.
            typeAssembly = origin switch {
                AssemblyDefinition asm => asm,
                TypeDefinition type => type.Module?.Assembly,
                IMemberDefinition member => member.DeclaringType.Module.Assembly,
                                   null => null,
                                   _ => throw new NotSupportedException()
            };

            if (typeAssembly != null && TryResolveTypeName(typeAssembly, parsedTypeName, out typeReference))
            {
                return(true);
            }

            // If type is not found in the caller's assembly, try in core assembly.
            typeAssembly = _context.TryResolve(PlatformAssemblies.CoreLib);
            if (typeAssembly != null && TryResolveTypeName(typeAssembly, parsedTypeName, out typeReference))
            {
                return(true);
            }

            // It is common to use Type.GetType for looking if a type is available.
            // If no type was found only warn and return null.
            if (needsAssemblyName && origin != null)
            {
                _context.LogWarning(new MessageOrigin(origin), DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeNameString);
            }

            typeAssembly = null;
            return(false);

            bool TryResolveTypeName(AssemblyDefinition assemblyDefinition, TypeName typeName, [NotNullWhen(true)] out TypeReference?typeReference)
            {
                typeReference = null;
                if (assemblyDefinition == null)
                {
                    return(false);
                }

                typeReference = ResolveTypeName(assemblyDefinition, typeName);
                return(typeReference != null);
            }
        }
Beispiel #11
0
        public TypeReference ResolveTypeName(string typeNameString, ICustomAttributeProvider origin, out AssemblyDefinition typeAssembly, bool needsAssemblyName = true)
        {
            typeAssembly = null;
            if (string.IsNullOrEmpty(typeNameString))
            {
                return(null);
            }

            TypeName parsedTypeName;

            try {
                parsedTypeName = TypeParser.ParseTypeName(typeNameString);
            } catch (ArgumentException) {
                return(null);
            } catch (System.IO.FileLoadException) {
                return(null);
            }

            if (parsedTypeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName)
            {
                typeAssembly = _context.TryResolve(assemblyQualifiedTypeName.AssemblyName.Name);
                if (typeAssembly == null)
                {
                    return(null);
                }

                return(ResolveTypeName(typeAssembly, assemblyQualifiedTypeName.TypeName));
            }

            // If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
            // search for the type in the calling object's assembly. If not found, look in the core
            // assembly.
            typeAssembly = origin switch {
                AssemblyDefinition asm => asm,
                TypeDefinition type => type.Module?.Assembly,
                IMemberDefinition member => member.DeclaringType.Module.Assembly,
                                   null => null,
                                   _ => throw new NotSupportedException()
            };

            if (typeAssembly != null && TryResolveTypeName(typeAssembly, parsedTypeName, out var typeRef))
            {
                return(typeRef);
            }

            // If type is not found in the caller's assembly, try in core assembly.
            typeAssembly = _context.TryResolve(PlatformAssemblies.CoreLib);
            if (typeAssembly != null && TryResolveTypeName(typeAssembly, parsedTypeName, out var typeRefFromSPCL))
            {
                return(typeRefFromSPCL);
            }

            // It is common to use Type.GetType for looking if a type is available.
            // If no type was found only warn and return null.
            if (needsAssemblyName && origin != null)
            {
                _context.LogWarning($"Type '{typeNameString}' was not found in the caller assembly nor in the base library. " +
                                    $"Type name strings used for dynamically accessing a type should be assembly qualified.",
                                    2105, new MessageOrigin(origin));
            }

            typeAssembly = null;
            return(null);

            bool TryResolveTypeName(AssemblyDefinition assemblyDefinition, TypeName typeName, out TypeReference typeReference)
            {
                typeReference = null;
                if (assemblyDefinition == null)
                {
                    return(false);
                }

                typeReference = ResolveTypeName(assemblyDefinition, typeName);
                return(typeReference != null);
            }
        }
Beispiel #12
0
        void PopulateCacheForType(TypeDefinition type)
        {
            // Avoid repeat scans of the same type
            if (!_typesWithPopulatedCache.Add(type))
            {
                return;
            }

            var callGraph      = new CompilerGeneratedCallGraph();
            var callingMethods = new HashSet <MethodDefinition> ();

            void ProcessMethod(MethodDefinition method)
            {
                bool isStateMachineMember = CompilerGeneratedNames.IsStateMachineType(method.DeclaringType.Name);

                if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(method.Name))
                {
                    if (!isStateMachineMember)
                    {
                        // If it's not a nested function, track as an entry point to the call graph.
                        var added = callingMethods.Add(method);
                        Debug.Assert(added);
                    }
                }
                else
                {
                    // We don't expect lambdas or local functions to be emitted directly into
                    // state machine types.
                    Debug.Assert(!isStateMachineMember);
                }

                // Discover calls or references to lambdas or local functions. This includes
                // calls to local functions, and lambda assignments (which use ldftn).
                if (method.Body != null)
                {
                    foreach (var instruction in method.Body.Instructions)
                    {
                        if (instruction.OpCode.OperandType != OperandType.InlineMethod)
                        {
                            continue;
                        }

                        MethodDefinition?lambdaOrLocalFunction = _context.TryResolve((MethodReference)instruction.Operand);
                        if (lambdaOrLocalFunction == null)
                        {
                            continue;
                        }

                        if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(lambdaOrLocalFunction.Name))
                        {
                            continue;
                        }

                        if (isStateMachineMember)
                        {
                            callGraph.TrackCall(method.DeclaringType, lambdaOrLocalFunction);
                        }
                        else
                        {
                            callGraph.TrackCall(method, lambdaOrLocalFunction);
                        }
                    }
                }

                // Discover state machine methods.
                if (!method.HasCustomAttributes)
                {
                    return;
                }

                foreach (var attribute in method.CustomAttributes)
                {
                    if (attribute.AttributeType.Namespace != "System.Runtime.CompilerServices")
                    {
                        continue;
                    }

                    switch (attribute.AttributeType.Name)
                    {
                    case "AsyncIteratorStateMachineAttribute":
                    case "AsyncStateMachineAttribute":
                    case "IteratorStateMachineAttribute":
                        TypeDefinition?stateMachineType = GetFirstConstructorArgumentAsType(attribute);
                        if (stateMachineType == null)
                        {
                            break;
                        }
                        Debug.Assert(stateMachineType.DeclaringType == type ||
                                     (CompilerGeneratedNames.IsGeneratedMemberName(stateMachineType.DeclaringType.Name) &&
                                      stateMachineType.DeclaringType.DeclaringType == type));
                        callGraph.TrackCall(method, stateMachineType);
                        if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd(stateMachineType, method))
                        {
                            var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType];
                            _context.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), stateMachineType.GetDisplayName());
                        }

                        break;
                    }
                }
            }

            // Look for state machine methods, and methods which call local functions.
            foreach (MethodDefinition method in type.Methods)
            {
                ProcessMethod(method);
            }

            // Also scan compiler-generated state machine methods (in case they have calls to nested functions),
            // and nested functions inside compiler-generated closures (in case they call other nested functions).

            // State machines can be emitted into lambda display classes, so we need to go down at least two
            // levels to find calls from iterator nested functions to other nested functions. We just recurse into
            // all compiler-generated nested types to avoid depending on implementation details.

            foreach (var nestedType in GetCompilerGeneratedNestedTypes(type))
            {
                foreach (var method in nestedType.Methods)
                {
                    ProcessMethod(method);
                }
            }

            // Now we've discovered the call graphs for calls to nested functions.
            // Use this to map back from nested functions to the declaring user methods.

            // Note: This maps all nested functions back to the user code, not to the immediately
            // declaring local function. The IL doesn't contain enough information in general for
            // us to determine the nesting of local functions and lambdas.

            // Note: this only discovers nested functions which are referenced from the user
            // code or its referenced nested functions. There is no reliable way to determine from
            // IL which user code an unused nested function belongs to.
            foreach (var userDefinedMethod in callingMethods)
            {
                foreach (var compilerGeneratedMember in callGraph.GetReachableMembers(userDefinedMethod))
                {
                    switch (compilerGeneratedMember)
                    {
                    case MethodDefinition nestedFunction:
                        Debug.Assert(CompilerGeneratedNames.IsLambdaOrLocalFunction(nestedFunction.Name));
                        // Nested functions get suppressions from the user method only.
                        if (!_compilerGeneratedMethodToUserCodeMethod.TryAdd(nestedFunction, userDefinedMethod))
                        {
                            var alreadyAssociatedMethod = _compilerGeneratedMethodToUserCodeMethod[nestedFunction];
                            _context.LogWarning(new MessageOrigin(userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), nestedFunction.GetDisplayName());
                        }
                        break;

                    case TypeDefinition stateMachineType:
                        // Types in the call graph are always state machine types
                        // For those all their methods are not tracked explicitly in the call graph; instead, they
                        // are represented by the state machine type itself.
                        // We are already tracking the association of the state machine type to the user code method
                        // above, so no need to track it here.
                        Debug.Assert(CompilerGeneratedNames.IsStateMachineType(stateMachineType.Name));
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
Beispiel #13
0
        static void GetAllOnType(TypeDefinition type, LinkContext context, bool declaredOnly, List <IMetadataTokenProvider> members, HashSet <TypeDefinition> types)
        {
            if (!types.Add(type))
            {
                return;
            }

            if (type.HasNestedTypes)
            {
                foreach (var nested in type.NestedTypes)
                {
                    members.Add(nested);
                    // Base types and interfaces of nested types are always included.
                    GetAllOnType(nested, context, declaredOnly: false, members, types);
                }
            }

            if (!declaredOnly)
            {
                var baseType = context.TryResolve(type.BaseType);
                if (baseType != null)
                {
                    GetAllOnType(baseType, context, declaredOnly: false, members, types);
                }
            }

            if (type.HasInterfaces)
            {
                if (declaredOnly)
                {
                    foreach (var iface in type.GetAllInterfaceImplementations(context, declaredOnly: true))
                    {
                        members.Add(iface);
                    }
                }
                else
                {
                    foreach (var iface in type.Interfaces)
                    {
                        members.Add(iface);
                        var interfaceType = context.TryResolve(iface.InterfaceType);
                        if (interfaceType == null)
                        {
                            continue;
                        }
                        GetAllOnType(interfaceType, context, declaredOnly: false, members, types);
                    }
                }
            }

            if (type.HasFields)
            {
                foreach (var f in type.Fields)
                {
                    members.Add(f);
                }
            }

            if (type.HasMethods)
            {
                foreach (var m in type.Methods)
                {
                    members.Add(m);
                }
            }

            if (type.HasProperties)
            {
                foreach (var p in type.Properties)
                {
                    members.Add(p);
                }
            }

            if (type.HasEvents)
            {
                foreach (var e in type.Events)
                {
                    members.Add(e);
                }
            }
        }
Beispiel #14
0
        public static IEnumerable <EventDefinition> GetEventsOnTypeHierarchy(this TypeDefinition thisType, LinkContext context, Func <EventDefinition, bool>?filter, BindingFlags?bindingFlags = BindingFlags.Default)
        {
            TypeDefinition?type       = thisType;
            bool           onBaseType = false;

            while (type != null)
            {
                foreach (var @event in type.Events)
                {
                    // Ignore private properties on a base type - those are completely ignored by reflection
                    // (anything private on the base type is not visible via the derived type)
                    // Note that properties themselves are not actually private, their accessors are
                    if (onBaseType &&
                        (@event.AddMethod == null || @event.AddMethod.IsPrivate) &&
                        (@event.RemoveMethod == null || @event.RemoveMethod.IsPrivate))
                    {
                        continue;
                    }

                    if (filter != null && !filter(@event))
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Static)
                    {
                        if ((@event.AddMethod != null) && [email protected])
                        {
                            continue;
                        }
                        if ((@event.RemoveMethod != null) && [email protected])
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Instance)
                    {
                        if ((@event.AddMethod != null) && @event.AddMethod.IsStatic)
                        {
                            continue;
                        }
                        if ((@event.RemoveMethod != null) && @event.RemoveMethod.IsStatic)
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public)
                    {
                        if ((@event.AddMethod == null || [email protected]) &&
                            (@event.RemoveMethod == null || [email protected]))
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic)
                    {
                        if ((@event.AddMethod != null) && @event.AddMethod.IsPublic)
                        {
                            continue;
                        }
                        if ((@event.RemoveMethod != null) && @event.RemoveMethod.IsPublic)
                        {
                            continue;
                        }
                    }

                    yield return(@event);
                }

                if ((bindingFlags & BindingFlags.DeclaredOnly) == BindingFlags.DeclaredOnly)
                {
                    yield break;
                }

                type       = context.TryResolve(type.BaseType);
                onBaseType = true;
            }
        }
Beispiel #15
0
        public static IEnumerable <PropertyDefinition> GetPropertiesOnTypeHierarchy(this TypeDefinition type, LinkContext context, Func <PropertyDefinition, bool> filter, BindingFlags?bindingFlags = BindingFlags.Default)
        {
            bool onBaseType = false;

            while (type != null)
            {
                foreach (var property in type.Properties)
                {
                    // Ignore private properties on a base type - those are completely ignored by reflection
                    // (anything private on the base type is not visible via the derived type)
                    // Note that properties themselves are not actually private, their accessors are
                    if (onBaseType &&
                        (property.GetMethod == null || property.GetMethod.IsPrivate) &&
                        (property.SetMethod == null || property.SetMethod.IsPrivate))
                    {
                        continue;
                    }

                    if (filter != null && !filter(property))
                    {
                        continue;
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Static)
                    {
                        if ((property.GetMethod != null) && !property.GetMethod.IsStatic)
                        {
                            continue;
                        }
                        if ((property.SetMethod != null) && !property.SetMethod.IsStatic)
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Instance | BindingFlags.Static)) == BindingFlags.Instance)
                    {
                        if ((property.GetMethod != null) && property.GetMethod.IsStatic)
                        {
                            continue;
                        }
                        if ((property.SetMethod != null) && property.SetMethod.IsStatic)
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public)
                    {
                        if ((property.GetMethod == null || !property.GetMethod.IsPublic) &&
                            (property.SetMethod == null || !property.SetMethod.IsPublic))
                        {
                            continue;
                        }
                    }

                    if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic)
                    {
                        if ((property.GetMethod != null) && property.GetMethod.IsPublic)
                        {
                            continue;
                        }
                        if ((property.SetMethod != null) && property.SetMethod.IsPublic)
                        {
                            continue;
                        }
                    }

                    yield return(property);
                }

                type       = context.TryResolve(type.BaseType);
                onBaseType = true;
            }
        }