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
///