using System; using System.Diagnostics.CodeAnalysis; using System.Reflection; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Cases.Expectations.Metadata; namespace Mono.Linker.Tests.Cases.Reflection { [SetupCSharpCompilerToUse ("csc")] [ExpectedNoWarnings] [SetupLinkerArgument ("--disable-opt", "unreachablebodies")] public class EventsUsedViaReflection { public static void Main () { new Foo (); // Needed to avoid lazy body marking stubbing TestGetEvents (); TestInternal (); TestBindingFlags (); TestUnknownBindingFlags (BindingFlags.Public); TestNullType (); TestDataFlowType (); TestDataFlowWithAnnotation (typeof (MyType)); TestIfElse (1); TestIgnoreCaseBindingFlags (); TestUnsupportedBindingFlags (); } [Kept] [RecognizedReflectionAccessPattern] static void TestGetEvents () { var events = typeof (Foo).GetEvents (); } [Kept] [RecognizedReflectionAccessPattern] // The event will not be kept as it's internal and the behavior of Type.GetEvents() is to only return public events // But we don't mark it as unrecognized access pattern - we did recognize it fully, just didn't find the event being asked for // The behavior of the code will not change by linking it: // - Without linking the GetEvents will return null // - After linking the GetEvents will still return null static void TestInternal () { var events = typeof (InternalEventType).GetEvents (); } [Kept] [RecognizedReflectionAccessPattern] static void TestBindingFlags () { var events = typeof (Bar).GetEvents (BindingFlags.NonPublic); } [Kept] [RecognizedReflectionAccessPattern] static void TestUnknownBindingFlags (BindingFlags bindingFlags) { // Since the binding flags are not known linker should mark all events on the type var events = typeof (UnknownBindingFlags).GetEvents (bindingFlags); } [Kept] [RecognizedReflectionAccessPattern] static void TestNullType () { Type type = null; var events = type.GetEvents (); } [Kept] static Type FindType () { return typeof (Foo); } [Kept] [UnrecognizedReflectionAccessPattern (typeof (Type), nameof (Type.GetEvents), new Type[] { typeof (BindingFlags) }, messageCode: "IL2075", message: new string[] { "FindType", "GetEvents" })] static void TestDataFlowType () { Type type = FindType (); var events = type.GetEvents (BindingFlags.Public | BindingFlags.Static); } [Kept] [RecognizedReflectionAccessPattern] static void TestDataFlowWithAnnotation ([KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))][DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] Type type) { var events = type.GetEvents (BindingFlags.Public | BindingFlags.Static); } [Kept] [RecognizedReflectionAccessPattern] static void TestIfElse (int i) { Type myType; if (i == 1) { myType = typeof (IfClass); } else { myType = typeof (ElseClass); } var events = myType.GetEvents (BindingFlags.Public); } [Kept] [RecognizedReflectionAccessPattern] static void TestIgnoreCaseBindingFlags () { var events = typeof (IgnoreCaseBindingFlagsClass).GetEvents (BindingFlags.IgnoreCase | BindingFlags.Public); } [Kept] [RecognizedReflectionAccessPattern] static void TestUnsupportedBindingFlags () { var events = typeof (PutRefDispPropertyBindingFlagsClass).GetEvents (BindingFlags.PutRefDispProperty); } [KeptMember (".ctor()")] class Foo { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler Event; } [Kept] class InternalEventType { internal event EventHandler Event; } class Bar { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] internal event EventHandler InternalEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] static event EventHandler Static; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] private event EventHandler PrivateEvent; public event EventHandler PublicEvent; } class UnknownBindingFlags { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] internal event EventHandler InternalEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] static event EventHandler Static; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] private event EventHandler PrivateEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler PublicEvent; } [Kept] class MyType { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler PublicEvent; private event EventHandler PrivateEvent; } class IfClass { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler IfEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler ElseEvent; } class ElseClass { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public static event EventHandler ElseEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler IfEvent; } class IgnoreCaseBindingFlagsClass { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler PublicEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] private event EventHandler MarkedDueToIgnoreCaseEvent; } [Kept] class PutRefDispPropertyBindingFlagsClass { [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] public event EventHandler PublicEvent; [Kept] [KeptBackingField] [KeptEventAddMethod] [KeptEventRemoveMethod] private event EventHandler MarkedDueToPutRefDispPropertyEvent; } } }