Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1920,11 +1920,12 @@ private bool TryFindPropertyOrField(Type type, string id, Expression? expression
switch (member)
{
case PropertyInfo property:
propertyOrFieldExpression = Expression.Property(expression, property);
var propertyIsStatic = property?.GetGetMethod().IsStatic ?? property?.GetSetMethod().IsStatic ?? false;
propertyOrFieldExpression = propertyIsStatic ? Expression.Property(null, property) : Expression.Property(expression, property);
return true;

case FieldInfo field:
propertyOrFieldExpression = Expression.Field(expression, field);
propertyOrFieldExpression = field.IsStatic ? Expression.Field(null, field) : Expression.Field(expression, field);
return true;

default:
Expand Down Expand Up @@ -2478,7 +2479,7 @@ private static Exception IncompatibleOperandsError(string opName, Expression lef
private MemberInfo? FindPropertyOrField(Type type, string memberName, bool staticAccess)
{
#if !(UAP10_0 || NETSTANDARD)
var extraBindingFlag = _parsingConfig.PrioritizePropertyOrFieldOverTheType && staticAccess ? BindingFlags.Static : BindingFlags.Instance;
var extraBindingFlag = _parsingConfig.PrioritizePropertyOrFieldOverTheType && staticAccess ? BindingFlags.Static : BindingFlags.Instance | BindingFlags.Static;
var bindingFlags = BindingFlags.Public | BindingFlags.DeclaredOnly | extraBindingFlag;
foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
{
Expand All @@ -2492,11 +2493,12 @@ private static Exception IncompatibleOperandsError(string opName, Expression lef
}
return null;
#else
var isCaseSensitive = _parsingConfig?.IsCaseSensitive == true;
var isCaseSensitive = _parsingConfig.IsCaseSensitive == true;
foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
{
// 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))));
MemberInfo? member = t.GetTypeInfo().DeclaredProperties
.FirstOrDefault(x => (!staticAccess || x.GetAccessors(true)[0].IsStatic) && (x.Name == memberName || (!isCaseSensitive && x.Name.Equals(memberName, StringComparison.OrdinalIgnoreCase))));
if (member != null)
{
return member;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FluentAssertions;
using System.Linq.Dynamic.Core.CustomTypeProviders;
using FluentAssertions;
using Xunit;

namespace System.Linq.Dynamic.Core.Tests.Parser
Expand All @@ -21,6 +22,67 @@ public void ParseMemberAccess_DictionaryIndex_On_Dynamic()
expression.ToString().Should().Be("System.Linq.Dynamic.Core.Tests.Parser.ProductDynamic[].Where(Param_0 => ([Dynamic] == Convert(\"First Product\", Object)))");
#endif
}

[Theory]
[InlineData("Prop", "TestProp")]
[InlineData("Field", "TestField")]
public void Parse_StaticPropertyOrField_In_StaticClass1(string name, string value)
{
// Arrange
var queryable = new int[1].AsQueryable();

// Act
var result = queryable.Select<string>($"{typeof(StaticClassExample)}.{name}").First();

// Assert
Assert.Equal(value, result);
}

[Theory]
[InlineData("Prop", "TestProp")]
[InlineData("Field", "TestField")]
public void Parse_StaticPropertyOrField_In_NonStaticClass1(string name, string value)
{
// Arrange
var queryable = new int[1].AsQueryable();

// Act
var result = queryable.Select<string>($"new {typeof(NonStaticClassExample)}().{name}").First();

// Assert
Assert.Equal(value, result);
}

[Theory]
[InlineData("Prop", "TestProp")]
[InlineData("Field", "TestField")]
public void Parse_StaticPropertyOrField_In_NonStaticClass2(string name, string value)
{
// Arrange
var queryable = new[] { new NonStaticClassExample() }.AsQueryable();

// Act
var result = queryable.Select<string>(name).First();

// Assert
Assert.Equal(value, result);
}
}

[DynamicLinqType]
public class StaticClassExample
{
public static string Prop { get; set; } = "TestProp";

public static string Field = "TestField";
}

[DynamicLinqType]
public class NonStaticClassExample
{
public static string Prop { get; set; } = "TestProp";

public static string Field = "TestField";
}

public class ProductDynamic
Expand Down
2 changes: 1 addition & 1 deletion test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void UsingStaticClassAsType_WhenAddedToDefaultDynamicLinqCustomTypeProvid
action.Should().NotThrow();
}

[Theory(Skip = "873")]
[Theory]
[InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
[InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsField[\"jwt\"]")]
[InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
Expand Down
Loading