From afaf666eff08435123eb649ac138419f4c9b9344 Mon Sep 17 00:00:00 2001 From: Noah Falk Date: Wed, 14 Jul 2021 03:29:04 -0700 Subject: DiagnosticSourceEventSource supports base class properties (#55613) 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. --- .../Diagnostics/DiagnosticSourceEventSource.cs | 4 +-- .../DiagnosticSourceEventSourceBridgeTests.cs | 40 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index 72f7572313f..d2ee34fe439 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -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."); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs index 2a59c8b48e4..ecf73aa7f06 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs @@ -490,6 +490,40 @@ namespace System.Diagnostics.Tests }).Dispose(); } + /// + /// Tests that DiagnosticSourceEventSource can read property values from base classes + /// + [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(); + } + /// /// Test that things work properly for Linux newline conventions. /// @@ -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; } + } + /// /// classes for test data. /// -- cgit v1.2.3