diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index a43b534e..a866c748 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -1909,7 +1909,7 @@ private Expression ParseMemberAccess(Type? type, Expression? expression, string?
return Expression.MakeIndex(expression, typeof(DynamicClass).GetProperty("Item"), new[] { Expression.Constant(id) });
}
#endif
- if (TryFindPropertyOrField(type!, id, expression, out var propertyOrFieldExpression))
+ if (TryFindPropertyOrField(type!, id, expression, out var propertyOrFieldExpression))
{
return propertyOrFieldExpression;
}
@@ -1954,7 +1954,9 @@ private bool TryFindPropertyOrField(Type type, string id, Expression? expression
switch (member)
{
case PropertyInfo property:
- var propertyIsStatic = property?.GetGetMethod().IsStatic ?? property?.GetSetMethod().IsStatic ?? false;
+ var getter = property.GetGetMethod(true);
+ var setter = property.GetSetMethod(true);
+ var propertyIsStatic = (getter?.IsStatic == true) || (setter?.IsStatic == true);
propertyOrFieldExpression = propertyIsStatic ? Expression.Property(null, property) : Expression.Property(expression, property);
return true;
@@ -2514,7 +2516,8 @@ private static Exception IncompatibleOperandsError(string opName, Expression lef
{
#if !(UAP10_0 || NETSTANDARD)
var extraBindingFlag = _parsingConfig.PrioritizePropertyOrFieldOverTheType && staticAccess ? BindingFlags.Static : BindingFlags.Instance | BindingFlags.Static;
- var bindingFlags = BindingFlags.Public | BindingFlags.DeclaredOnly | extraBindingFlag;
+ var visibilityFlags = BindingFlags.Public | (_parsingConfig.AllowAccessToNonPublicMembers ? BindingFlags.NonPublic : 0);
+ var bindingFlags = visibilityFlags | BindingFlags.DeclaredOnly | extraBindingFlag;
foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
{
var findMembersType = _parsingConfig?.IsCaseSensitive == true ? Type.FilterName : Type.FilterNameIgnoreCase;
@@ -2532,14 +2535,18 @@ private static Exception IncompatibleOperandsError(string opName, Expression lef
{
// Try to find a property with the specified memberName
MemberInfo? member = t.GetTypeInfo().DeclaredProperties
- .FirstOrDefault(x => (!staticAccess || x.GetAccessors(true)[0].IsStatic) && (x.Name == memberName || (!isCaseSensitive && x.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase))));
+ .FirstOrDefault(x => (!staticAccess || x.GetAccessors(true)[0].IsStatic)
+ && (x.Name == memberName || (!isCaseSensitive && x.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase)))
+ && (_parsingConfig.AllowAccessToNonPublicMembers || x.GetAccessors(true).Any(a => a.IsPublic)));
if (member != null)
{
return member;
}
// If no property is found, try to get a field with the specified memberName
- member = t.GetTypeInfo().DeclaredFields.FirstOrDefault(x => (!staticAccess || x.IsStatic) && ((x.Name == memberName) || (!isCaseSensitive && x.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase))));
+ member = t.GetTypeInfo().DeclaredFields.FirstOrDefault(x => (!staticAccess || x.IsStatic)
+ && ((x.Name == memberName) || (!isCaseSensitive && x.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase)))
+ && (_parsingConfig.AllowAccessToNonPublicMembers || x.IsPublic));
if (member != null)
{
return member;
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index 300ff594..f22097f0 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -319,4 +319,11 @@ public IQueryableAnalyzer QueryableAnalyzer
/// Default value is false.
///
public bool AllowEqualsAndToStringMethodsOnObject { get; set; }
+
+ ///
+ /// When set to true, the parser will consider non-public members (internal and private)
+ /// during property/field lookup where the runtime permits access (e.g., via InternalsVisibleTo).
+ /// Default value is false.
+ ///
+ public bool AllowAccessToNonPublicMembers { get; set; }
}
\ No newline at end of file