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 c7b92ad12ff2de..b598a75fa85e81 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -1345,7 +1345,19 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) } else { - PropertyInfo? propertyInfo = typeInfo.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + PropertyInfo? propertyInfo = typeInfo.GetDeclaredProperty(propertyName); + if (propertyInfo == null) + { + foreach (PropertyInfo pi in typeInfo.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) + { + if (pi.Name == propertyName) + { + propertyInfo = pi; + break; + } + } + } + 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 c6f16f634022c5..b3fb43640498b9 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs @@ -524,6 +524,39 @@ public void TestBaseClassProperties() }).Dispose(); } + /// + /// Tests that DiagnosticSourceEventSource can read property values from base classes + /// + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void TestBaseClassDuplicateProperties() + { + 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=Url\r\n"); + + /***************************************************************************************/ + // Emit an event that matches the first pattern. + MyClass val = new MyOtherDerivedClass() { Url = "MyUrl", Point = new MyDerivedPoint() { X = 3, Y = 5 } }; + 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(4, eventSourceListener.LastEvent.Arguments.Count); + Assert.Equal("3", eventSourceListener.LastEvent.Arguments["Point_X"]); + Assert.Equal("5", eventSourceListener.LastEvent.Arguments["Point_Y"]); + Assert.Equal("MyUrl", eventSourceListener.LastEvent.Arguments["Url"]); + eventSourceListener.ResetEventCountAndLastEvent(); + } + }).Dispose(); + } + /// /// Test that things work properly for Linux newline conventions. /// @@ -1353,6 +1386,11 @@ internal class MyDerivedClass : MyClass public string AnotherString { get; set; } } + internal class MyOtherDerivedClass : MyClass + { + public new MyDerivedPoint Point { get; set; } + } + /// /// classes for test data. /// @@ -1362,6 +1400,9 @@ internal class MyPoint public int Y { get; set; } } + internal class MyDerivedPoint : MyPoint + { } + /// /// classes for test data ///