From 2e1fc83cc79ed1ebf0cc55a6f12fbfde54eb8e32 Mon Sep 17 00:00:00 2001 From: Koen Date: Sun, 2 Aug 2026 01:13:50 +0000 Subject: [PATCH] include non-public accessors when resolving implementing properties --- .../Extensions/TypeExtensions.cs | 2 +- .../Extensions/TypeExtensionsTests.cs | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/ExpressiveSharp/Extensions/TypeExtensions.cs b/src/ExpressiveSharp/Extensions/TypeExtensions.cs index 2e0df423..f54cdfcd 100644 --- a/src/ExpressiveSharp/Extensions/TypeExtensions.cs +++ b/src/ExpressiveSharp/Extensions/TypeExtensions.cs @@ -122,7 +122,7 @@ private static MethodInfo GetImplementingMethod(this Type derivedType, MethodInf public static PropertyInfo GetImplementingProperty(this Type derivedType, PropertyInfo propertyInfo) { - var accessor = propertyInfo.GetAccessors()[0]; + var accessor = propertyInfo.GetAccessors(true)[0]; var implementingAccessor = derivedType.GetImplementingMethod(accessor); if (implementingAccessor == accessor) diff --git a/tests/ExpressiveSharp.Tests/Extensions/TypeExtensionsTests.cs b/tests/ExpressiveSharp.Tests/Extensions/TypeExtensionsTests.cs index fc2a1fc7..8d05524a 100644 --- a/tests/ExpressiveSharp.Tests/Extensions/TypeExtensionsTests.cs +++ b/tests/ExpressiveSharp.Tests/Extensions/TypeExtensionsTests.cs @@ -110,4 +110,26 @@ public void GetConcreteProperty_SameDeclaringType_ReturnsOriginal() Assert.AreEqual(animalName, result); } + + public interface IHidden + { + internal string Secret { get; } + } + + public class HiddenImpl : IHidden + { + string IHidden.Secret => "s"; + } + + [TestMethod] + public void GetConcreteProperty_InterfacePropertyWithNonPublicAccessor_DoesNotThrow() + { + var interfaceProperty = typeof(IHidden) + .GetProperty(nameof(IHidden.Secret), BindingFlags.NonPublic | BindingFlags.Instance); + Assert.IsNotNull(interfaceProperty); + + var result = typeof(HiddenImpl).GetConcreteProperty(interfaceProperty); + + Assert.IsNotNull(result); + } }