DiagnosticSourceEventSource supports base class properties (#55613)
authorNoah Falk <noahfalk@users.noreply.github.com>
Wed, 14 Jul 2021 10:29:04 +0000 (03:29 -0700)
committerGitHub <noreply@github.com>
Wed, 14 Jul 2021 10:29:04 +0000 (06:29 -0400)
Fixes #41300

Previously DiagnosticSourceEventSource would only iterate and recognize properties that were declared on the most derived type.
Now it can capture properties that were inherited from a base class too.

src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs
src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs

index 72f7572313f90801e4f0832015b9d0d6e0224514..d2ee34fe439d9f49906a1fe379342fffc5cdb637 100644 (file)
@@ -1099,7 +1099,7 @@ namespace System.Diagnostics
             {
                 TransformSpec? newSerializableArgs = null;
                 TypeInfo curTypeInfo = type.GetTypeInfo();
-                foreach (PropertyInfo property in curTypeInfo.DeclaredProperties)
+                foreach (PropertyInfo property in curTypeInfo.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                 {
                     // prevent TransformSpec from attempting to implicitly transform index properties
                     if (property.GetMethod == null || property.GetMethod!.GetParameters().Length > 0)
@@ -1319,7 +1319,7 @@ namespace System.Diagnostics
                         }
                         else
                         {
-                            PropertyInfo? propertyInfo = typeInfo.GetDeclaredProperty(propertyName);
+                            PropertyInfo? propertyInfo = typeInfo.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
                             if (propertyInfo == null)
                             {
                                 Log.Message($"Property {propertyName} not found on {type}. Ensure the name is spelled correctly. If you published the application with PublishTrimmed=true, ensure the property was not trimmed away.");
index 2a59c8b48e4f6c2aff14d1ba0029e83a1e9389fa..ecf73aa7f06cb79eab2c1fc115c7780fc5799206 100644 (file)
@@ -490,6 +490,40 @@ namespace System.Diagnostics.Tests
             }).Dispose();
         }
 
+        /// <summary>
+        /// Tests that DiagnosticSourceEventSource can read property values from base classes
+        /// </summary>
+        [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+        public void TestBaseClassProperties()
+        {
+            RemoteExecutor.Invoke(() =>
+            {
+                using (var eventSourceListener = new TestDiagnosticSourceEventListener())
+                using (var diagnosticSourceListener = new DiagnosticListener("TestBaseClassProperties"))
+                {
+                    Assert.Equal(0, eventSourceListener.EventCount);
+                    eventSourceListener.Enable(
+                        "  TestBaseClassProperties/TestEvent1:Point_X=Point.X;Point_Y=Point.Y;Url_2=Url2\r\n");
+
+                    /***************************************************************************************/
+                    // Emit an event that matches the first pattern.
+                    MyClass val = new MyDerivedClass() { Url = "MyUrl", Point = new MyPoint() { X = 3, Y = 5 }, Url2 = "Second url", AnotherString = "another" };
+                    if (diagnosticSourceListener.IsEnabled("TestEvent1"))
+                        diagnosticSourceListener.Write("TestEvent1", val);
+
+                    Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted.
+                    Assert.Equal("TestBaseClassProperties", eventSourceListener.LastEvent.SourceName);
+                    Assert.Equal("TestEvent1", eventSourceListener.LastEvent.EventName);
+                    Assert.Equal(7, eventSourceListener.LastEvent.Arguments.Count);
+                    Assert.Equal("another", eventSourceListener.LastEvent.Arguments["AnotherString"]);
+                    Assert.Equal("3", eventSourceListener.LastEvent.Arguments["Point_X"]);
+                    Assert.Equal("5", eventSourceListener.LastEvent.Arguments["Point_Y"]);
+                    Assert.Equal("Second url", eventSourceListener.LastEvent.Arguments["Url_2"]);
+                    eventSourceListener.ResetEventCountAndLastEvent();
+                }
+            }).Dispose();
+        }
+
         /// <summary>
         /// Test that things work properly for Linux newline conventions.
         /// </summary>
@@ -1314,6 +1348,12 @@ namespace System.Diagnostics.Tests
         public MyPoint Point { get; set; }
     }
 
+    internal class MyDerivedClass : MyClass
+    {
+        public string Url2 { get; set; }
+        public string AnotherString { get; set; }
+    }
+
     /// <summary>
     /// classes for test data.
     /// </summary>