From 36d5b91be3f860301ac93772166594c69af80e35 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Fri, 29 May 2020 18:05:44 +0000 Subject: [PATCH 1/4] Factor out binding logic for DynamicallyAccessedMemberTypes This will be used for DynamicDependencyAttribute as well. --- .../DynamicallyAccessedMembersBinder.cs | 297 ++++++++++++++++ .../ReflectionMethodBodyScanner.cs | 319 ++++-------------- 2 files changed, 372 insertions(+), 244 deletions(-) create mode 100644 src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs new file mode 100644 index 000000000000..ea832de62064 --- /dev/null +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Mono.Cecil; + +namespace Mono.Linker.Dataflow +{ + internal static class DynamicallyAccessedMembersBinder + { + // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returts a single member + // which is the type itself. + public static IEnumerable GetDynamicallyAccessedMembers (TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) + { + if (memberTypes == DynamicallyAccessedMemberTypes.All) { + yield return typeDefinition; + yield break; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicConstructors)) { + foreach (var c in GetConstructorsOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return c; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors)) { + foreach (var c in GetConstructorsOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return c; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.DefaultConstructor)) { + foreach (var c in GetConstructorsOnType (typeDefinition, filter: m => m.IsPublic && m.Parameters.Count == 0)) + yield return c; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicMethods)) { + foreach (var m in GetMethodsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return m; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods)) { + foreach (var m in GetMethodsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return m; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicFields)) { + foreach (var f in GetFieldsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return f; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicFields)) { + foreach (var f in GetFieldsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return f; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)) { + foreach (var t in GetNestedTypesOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return t; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicNestedTypes)) { + foreach (var t in GetNestedTypesOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return t; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicProperties)) { + foreach (var p in GetPropertiesOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return p; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties)) { + foreach (var p in GetPropertiesOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return p; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicEvents)) { + foreach (var e in GetEventsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + yield return e; + } + + if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents)) { + foreach (var e in GetEventsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + yield return e; + } + } + + public static IEnumerable GetConstructorsOnType (TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) + { + foreach (var method in type.Methods) { + if (!method.IsConstructor) + continue; + + 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; + } + } + + public static IEnumerable GetMethodsOnTypeHierarchy (TypeDefinition type, Func 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 = type.BaseType?.Resolve (); + onBaseType = true; + } + } + + public static IEnumerable GetFieldsOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + { + 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; + } + + type = type.BaseType?.Resolve (); + onBaseType = true; + } + } + + public static IEnumerable GetNestedTypesOnType (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + { + foreach (var nestedType in type.NestedTypes) { + if (filter != null && !filter (nestedType)) + continue; + + if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public) { + if (!nestedType.IsNestedPublic) + continue; + } + + if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic) { + if (nestedType.IsNestedPublic) + continue; + } + + yield return nestedType; + } + } + + public static IEnumerable GetPropertiesOnTypeHierarchy (TypeDefinition type, Func 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 = type.BaseType?.Resolve (); + onBaseType = true; + } + } + + public static IEnumerable GetEventsOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + { + 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) && !@event.AddMethod.IsStatic) continue; + if ((@event.RemoveMethod != null) && !@event.RemoveMethod.IsStatic) 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 || !@event.AddMethod.IsPublic) + && (@event.RemoveMethod == null || !@event.RemoveMethod.IsPublic)) + 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; + } + + type = type.BaseType?.Resolve (); + onBaseType = true; + } + } + } +} \ No newline at end of file diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 7f3cbd508b54..ac64905dcfb4 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1237,178 +1237,102 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberKinds) { - if (requiredMemberKinds == DynamicallyAccessedMemberTypes.All) { - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); - return; - } - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicConstructors)) - MarkConstructorsOnType (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors)) - MarkConstructorsOnType (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.DefaultConstructor)) - MarkConstructorsOnType (ref reflectionContext, typeDefinition, filter: m => m.IsPublic && m.Parameters.Count == 0); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicMethods)) - MarkMethodsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods)) - MarkMethodsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicFields)) - MarkFieldsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicFields)) - MarkFieldsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); - - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)) - MarkNestedTypesOnType (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); + foreach (var member in DynamicallyAccessedMembersBinder.GetDynamicallyAccessedMembers (typeDefinition, requiredMemberKinds)) { + if (member == typeDefinition) { + var source = reflectionContext.Source; + reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + continue; + } + switch (member) { + case MethodDefinition method: + MarkMethod (ref reflectionContext, typeDefinition, method); + break; + case FieldDefinition field: + MarkField (ref reflectionContext, typeDefinition, field); + break; + case TypeDefinition nestedType: + MarkNestedType (ref reflectionContext, typeDefinition, nestedType); + break; + case PropertyDefinition property: + MarkProperty (ref reflectionContext, typeDefinition, property); + break; + case EventDefinition @event: + MarkEvent (ref reflectionContext, typeDefinition, @event); + break; + } + } + } - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicNestedTypes)) - MarkNestedTypesOnType (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); + void MarkMethod (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, MethodDefinition method) + { + var source = reflectionContext.Source; + reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + } - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicProperties)) - MarkPropertiesOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); + void MarkNestedType (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, TypeDefinition nestedType) + { + var source = reflectionContext.Source; + reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkType (nestedType, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + } - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties)) - MarkPropertiesOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); + void MarkField (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, FieldDefinition field) + { + var source = reflectionContext.Source; + reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + } - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.NonPublicEvents)) - MarkEventsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic); + void MarkProperty (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, PropertyDefinition property) + { + var source = reflectionContext.Source; + var dependencyInfo = new DependencyInfo (DependencyKind.AccessedViaReflection, source); + reflectionContext.RecordRecognizedPattern (property, () => { + // Marking the property itself actually doesn't keep it (it only marks its attributes and records the dependency), we have to mark the methods on it + _markStep.MarkProperty (property, dependencyInfo); + // TODO - this is sort of questionable - when somebody asks for a property they probably want to call either get or set + // but linker tracks those separately, and so accessing the getter/setter will raise a warning as it's potentially trimmed. + // So including them here doesn't actually remove the warning even if the code is written correctly. + _markStep.MarkMethodIfNotNull (property.GetMethod, dependencyInfo); + _markStep.MarkMethodIfNotNull (property.SetMethod, dependencyInfo); + _markStep.MarkMethodsIf (property.OtherMethods, m => true, dependencyInfo); + }); + } - if (requiredMemberKinds.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents)) - MarkEventsOnTypeHierarchy (ref reflectionContext, typeDefinition, filter: null, bindingFlags: BindingFlags.Public); + void MarkEvent (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, EventDefinition @event) + { + var dependencyInfo = new DependencyInfo (DependencyKind.AccessedViaReflection, reflectionContext.Source); + reflectionContext.RecordRecognizedPattern (@event, () => { + // MarkEvent actually marks the add/remove/invoke methods as well, so no need to mark those explicitly + _markStep.MarkEvent (@event, dependencyInfo); + _markStep.MarkMethodsIf (@event.OtherMethods, m => true, dependencyInfo); + }); } void MarkConstructorsOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) { - foreach (var method in type.Methods) { - if (!method.IsConstructor) - continue; - - 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; - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); - } + foreach (var ctor in DynamicallyAccessedMembersBinder.GetConstructorsOnType (type, filter, bindingFlags)) + MarkMethod (ref reflectionContext, type, ctor); } void MarkMethodsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func 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; - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); - } - - type = type.BaseType?.Resolve (); - onBaseType = true; - } + foreach (var method in DynamicallyAccessedMembersBinder.GetMethodsOnTypeHierarchy (type, filter, bindingFlags)) + MarkMethod (ref reflectionContext, type, method); } void MarkFieldsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { - 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; - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); - } - - type = type.BaseType?.Resolve (); - onBaseType = true; - } + foreach (var field in DynamicallyAccessedMembersBinder.GetFieldsOnTypeHierarchy (type, filter, bindingFlags)) + MarkField (ref reflectionContext, type, field); } TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { var result = new ArrayBuilder (); - foreach (var nestedType in type.NestedTypes) { - if (filter != null && !filter (nestedType)) - continue; - - if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.Public) { - if (!nestedType.IsNestedPublic) - continue; - } - - if ((bindingFlags & (BindingFlags.Public | BindingFlags.NonPublic)) == BindingFlags.NonPublic) { - if (nestedType.IsNestedPublic) - continue; - } - + foreach (var nestedType in DynamicallyAccessedMembersBinder.GetNestedTypesOnType (type, filter, bindingFlags)) { result.Add (nestedType); - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkType (nestedType, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + MarkNestedType (ref reflectionContext, type, nestedType); } return result.ToArray (); @@ -1416,107 +1340,14 @@ TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionC void MarkPropertiesOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func 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; - } - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (property, () => { - // Marking the property itself actually doesn't keep it (it only marks its attributes and records the dependency), we have to mark the methods on it - _markStep.MarkProperty (property, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - // TODO - this is sort of questionable - when somebody asks for a property they probably want to call either get or set - // but linker tracks those separately, and so accessing the getter/setter will raise a warning as it's potentially trimmed. - // So including them here doesn't actually remove the warning even if the code is written correctly. - _markStep.MarkMethodIfNotNull (property.GetMethod, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - _markStep.MarkMethodIfNotNull (property.SetMethod, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - _markStep.MarkMethodsIf (property.OtherMethods, m => true, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - }); - } - - type = type.BaseType?.Resolve (); - onBaseType = true; - } + foreach (var property in DynamicallyAccessedMembersBinder.GetPropertiesOnTypeHierarchy (type, filter, bindingFlags)) + MarkProperty (ref reflectionContext, type, property); } void MarkEventsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { - 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) && !@event.AddMethod.IsStatic) continue; - if ((@event.RemoveMethod != null) && !@event.RemoveMethod.IsStatic) 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 || !@event.AddMethod.IsPublic) - && (@event.RemoveMethod == null || !@event.RemoveMethod.IsPublic)) - 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; - } - - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (@event, () => { - // MarkEvent actually marks the add/remove/invoke methods as well, so no need to mark those explicitly - _markStep.MarkEvent (@event, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - _markStep.MarkMethodsIf (@event.OtherMethods, m => true, new DependencyInfo (DependencyKind.AccessedViaReflection, source)); - }); - } - - type = type.BaseType?.Resolve (); - onBaseType = true; - } + foreach (var @event in DynamicallyAccessedMembersBinder.GetEventsOnTypeHierarchy (type, filter, bindingFlags)) + MarkEvent (ref reflectionContext, type, @event); } string GetValueDescriptionForErrorMessage (ValueNode value) From 08f973f806e70f93ec33d92374388d6c27fd5a6b Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 27 May 2020 17:20:54 +0000 Subject: [PATCH 2/4] Use null sentinel Instead of type itself for DynamicallyAccessedMemberTypes.All --- .../DynamicallyAccessedMembersBinder.cs | 5 ++--- .../Linker.Dataflow/ReflectionMethodBodyScanner.cs | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs index ea832de62064..a6d8f24bc3cd 100644 --- a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs @@ -8,12 +8,11 @@ namespace Mono.Linker.Dataflow { internal static class DynamicallyAccessedMembersBinder { - // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returts a single member - // which is the type itself. + // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returns a single null result. public static IEnumerable GetDynamicallyAccessedMembers (TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) { if (memberTypes == DynamicallyAccessedMemberTypes.All) { - yield return typeDefinition; + yield return null; yield break; } diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index ac64905dcfb4..7c6814fe2551 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1237,13 +1237,7 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberKinds) { - foreach (var member in DynamicallyAccessedMembersBinder.GetDynamicallyAccessedMembers (typeDefinition, requiredMemberKinds)) { - if (member == typeDefinition) { - var source = reflectionContext.Source; - reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); - continue; - } switch (member) { case MethodDefinition method: MarkMethod (ref reflectionContext, typeDefinition, method); @@ -1260,6 +1254,10 @@ void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflect case EventDefinition @event: MarkEvent (ref reflectionContext, typeDefinition, @event); break; + case null: + var source = reflectionContext.Source; + reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, new DependencyInfo (DependencyKind.AccessedViaReflection, source))); + break; } } } From a6d4601fb1c2ffc026ac79aee5f602040e69af45 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Fri, 29 May 2020 17:53:44 +0000 Subject: [PATCH 3/4] PR feedback - Add clarifying comments --- src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs index a6d8f24bc3cd..2ab5db908688 100644 --- a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs @@ -9,6 +9,8 @@ namespace Mono.Linker.Dataflow internal static class DynamicallyAccessedMembersBinder { // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returns a single null result. + // This sentinel value allows callers to handle the case where MemberTypes.All conceptually binds to the entire type + // including all recursive nested members. public static IEnumerable GetDynamicallyAccessedMembers (TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) { if (memberTypes == DynamicallyAccessedMemberTypes.All) { From 03a732bc1af87c83df0e04db1e8cc33b0142307e Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 1 Jun 2020 17:41:33 +0000 Subject: [PATCH 4/4] Change namespace and use extension methods --- .../DynamicallyAccessedMembersBinder.cs | 42 +++++++++---------- .../ReflectionMethodBodyScanner.cs | 14 +++---- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs index 2ab5db908688..bcd6a0747d1f 100644 --- a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs @@ -4,14 +4,14 @@ using System.Reflection; using Mono.Cecil; -namespace Mono.Linker.Dataflow +namespace Mono.Linker { internal static class DynamicallyAccessedMembersBinder { // Returns the members of the type bound by memberTypes. For MemberTypes.All, this returns a single null result. // This sentinel value allows callers to handle the case where MemberTypes.All conceptually binds to the entire type // including all recursive nested members. - public static IEnumerable GetDynamicallyAccessedMembers (TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) + public static IEnumerable GetDynamicallyAccessedMembers (this TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes memberTypes) { if (memberTypes == DynamicallyAccessedMemberTypes.All) { yield return null; @@ -19,72 +19,72 @@ public static IEnumerable GetDynamicallyAccessedMembers (Type } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicConstructors)) { - foreach (var c in GetConstructorsOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var c in typeDefinition.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return c; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicConstructors)) { - foreach (var c in GetConstructorsOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var c in typeDefinition.GetConstructorsOnType (filter: null, bindingFlags: BindingFlags.Public)) yield return c; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.DefaultConstructor)) { - foreach (var c in GetConstructorsOnType (typeDefinition, filter: m => m.IsPublic && m.Parameters.Count == 0)) + foreach (var c in typeDefinition.GetConstructorsOnType (filter: m => m.IsPublic && m.Parameters.Count == 0)) yield return c; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicMethods)) { - foreach (var m in GetMethodsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return m; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicMethods)) { - foreach (var m in GetMethodsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var m in typeDefinition.GetMethodsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) yield return m; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicFields)) { - foreach (var f in GetFieldsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return f; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicFields)) { - foreach (var f in GetFieldsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var f in typeDefinition.GetFieldsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) yield return f; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)) { - foreach (var t in GetNestedTypesOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var t in typeDefinition.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return t; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicNestedTypes)) { - foreach (var t in GetNestedTypesOnType (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var t in typeDefinition.GetNestedTypesOnType (filter: null, bindingFlags: BindingFlags.Public)) yield return t; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicProperties)) { - foreach (var p in GetPropertiesOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return p; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicProperties)) { - foreach (var p in GetPropertiesOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var p in typeDefinition.GetPropertiesOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) yield return p; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.NonPublicEvents)) { - foreach (var e in GetEventsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.NonPublic)) + foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.NonPublic)) yield return e; } if (memberTypes.HasFlag (DynamicallyAccessedMemberTypes.PublicEvents)) { - foreach (var e in GetEventsOnTypeHierarchy (typeDefinition, filter: null, bindingFlags: BindingFlags.Public)) + foreach (var e in typeDefinition.GetEventsOnTypeHierarchy (filter: null, bindingFlags: BindingFlags.Public)) yield return e; } } - public static IEnumerable GetConstructorsOnType (TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) + public static IEnumerable GetConstructorsOnType (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) { foreach (var method in type.Methods) { if (!method.IsConstructor) @@ -109,7 +109,7 @@ public static IEnumerable GetConstructorsOnType (TypeDefinitio } } - public static IEnumerable GetMethodsOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) + public static IEnumerable GetMethodsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) { bool onBaseType = false; while (type != null) { @@ -149,7 +149,7 @@ public static IEnumerable GetMethodsOnTypeHierarchy (TypeDefin } } - public static IEnumerable GetFieldsOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + public static IEnumerable GetFieldsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { @@ -185,7 +185,7 @@ public static IEnumerable GetFieldsOnTypeHierarchy (TypeDefinit } } - public static IEnumerable GetNestedTypesOnType (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + public static IEnumerable GetNestedTypesOnType (this TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { foreach (var nestedType in type.NestedTypes) { if (filter != null && !filter (nestedType)) @@ -205,7 +205,7 @@ public static IEnumerable GetNestedTypesOnType (TypeDefinition t } } - public static IEnumerable GetPropertiesOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + public static IEnumerable GetPropertiesOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { @@ -250,7 +250,7 @@ public static IEnumerable GetPropertiesOnTypeHierarchy (Type } } - public static IEnumerable GetEventsOnTypeHierarchy (TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) + public static IEnumerable GetEventsOnTypeHierarchy (this TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { bool onBaseType = false; while (type != null) { diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 7c6814fe2551..7c0695ccc573 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -1237,7 +1237,7 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberKinds) { - foreach (var member in DynamicallyAccessedMembersBinder.GetDynamicallyAccessedMembers (typeDefinition, requiredMemberKinds)) { + foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (requiredMemberKinds)) { switch (member) { case MethodDefinition method: MarkMethod (ref reflectionContext, typeDefinition, method); @@ -1308,19 +1308,19 @@ void MarkEvent (ref ReflectionPatternContext reflectionContext, TypeDefinition t void MarkConstructorsOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) { - foreach (var ctor in DynamicallyAccessedMembersBinder.GetConstructorsOnType (type, filter, bindingFlags)) + foreach (var ctor in type.GetConstructorsOnType (filter, bindingFlags)) MarkMethod (ref reflectionContext, type, ctor); } void MarkMethodsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags? bindingFlags = null) { - foreach (var method in DynamicallyAccessedMembersBinder.GetMethodsOnTypeHierarchy (type, filter, bindingFlags)) + foreach (var method in type.GetMethodsOnTypeHierarchy (filter, bindingFlags)) MarkMethod (ref reflectionContext, type, method); } void MarkFieldsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { - foreach (var field in DynamicallyAccessedMembersBinder.GetFieldsOnTypeHierarchy (type, filter, bindingFlags)) + foreach (var field in type.GetFieldsOnTypeHierarchy (filter, bindingFlags)) MarkField (ref reflectionContext, type, field); } @@ -1328,7 +1328,7 @@ TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionC { var result = new ArrayBuilder (); - foreach (var nestedType in DynamicallyAccessedMembersBinder.GetNestedTypesOnType (type, filter, bindingFlags)) { + foreach (var nestedType in type.GetNestedTypesOnType (filter, bindingFlags)) { result.Add (nestedType); MarkNestedType (ref reflectionContext, type, nestedType); } @@ -1338,13 +1338,13 @@ TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionC void MarkPropertiesOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { - foreach (var property in DynamicallyAccessedMembersBinder.GetPropertiesOnTypeHierarchy (type, filter, bindingFlags)) + foreach (var property in type.GetPropertiesOnTypeHierarchy (filter, bindingFlags)) MarkProperty (ref reflectionContext, type, property); } void MarkEventsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func filter, BindingFlags bindingFlags = BindingFlags.Default) { - foreach (var @event in DynamicallyAccessedMembersBinder.GetEventsOnTypeHierarchy (type, filter, bindingFlags)) + foreach (var @event in type.GetEventsOnTypeHierarchy (filter, bindingFlags)) MarkEvent (ref reflectionContext, type, @event); }