Skip to content

Commit cbd15b1

Browse files
committed
Update DynamicGetMemberBinder to add BindingRestrictions to DynamicMetaObject
1 parent b038e62 commit cbd15b1

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

src-console/ConsoleApp_net6.0/Program.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ private static void Q912()
8383
// GROUPING SET 1: (Region, Product)
8484
var detailed = rows
8585
.GroupBy("new (Region, Product)")
86-
.Select<GroupedSalesData>("new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)");
86+
.Select("new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)");
8787

8888
// GROUPING SET 2: (Region)
8989
var regionSubtotal = rows
9090
.GroupBy("Region")
91-
.Select<GroupedSalesData>("new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)");
91+
.Select("new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)");
9292

93-
var combined = detailed.Concat(regionSubtotal);
93+
var combined = detailed.ToDynamicArray().Concat(regionSubtotal.ToDynamicArray()).AsQueryable();
9494
var ordered = combined.OrderBy("Product").ToDynamicList();
9595

9696
int x = 9;

src/System.Linq.Dynamic.Core/DynamicGetMemberBinder.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ public DynamicGetMemberBinder(string name, ParsingConfig? config) : base(name, c
2121

2222
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion)
2323
{
24-
var instance = Expression.Call(
24+
var methodCallExpression = Expression.Call(
2525
DynamicGetMemberMethod,
2626
target.Expression,
2727
Expression.Constant(Name),
2828
Expression.Constant(IgnoreCase));
2929

30-
return DynamicMetaObject.Create(target.Value!, instance);
30+
// Fix #907 and #912: "The result of the dynamic binding produced by the object with type '<>f__AnonymousType1`4' for the binder 'System.Linq.Dynamic.Core.DynamicGetMemberBinder' needs at least one restriction.".
31+
var restrictions = BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value);
32+
return new DynamicMetaObject(methodCallExpression, restrictions, target.Value!);
3133
}
3234

3335
public static object? GetDynamicMember(object value, string name, bool ignoreCase)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace System.Linq.Dynamic.Core.Tests;
5+
6+
public class DynamicGetMemberBinderTests
7+
{
8+
public class SalesData
9+
{
10+
public string Region { get; set; } = null!;
11+
12+
public string Product { get; set; } = null!;
13+
14+
public string Sales { get; set; } = null!;
15+
}
16+
17+
[Fact]
18+
public void DynamicGetMemberBinder_Test1()
19+
{
20+
// Arrange
21+
var rows = new SalesData[]
22+
{
23+
new() { Region = "North", Product = "Widget", Sales = "100" },
24+
new() { Region = "North", Product = "Gadget", Sales = "150" },
25+
new() { Region = "South", Product = "Widget", Sales = "200" },
26+
new() { Region = "South", Product = "Gadget", Sales = "100" },
27+
new() { Region = "North", Product = "Widget", Sales = "50" }
28+
}.AsQueryable();
29+
30+
// Act
31+
var grouping1 = rows
32+
.GroupBy("new (Region, Product)")
33+
.Select("new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)");
34+
35+
var grouping2 = rows
36+
.GroupBy("Region")
37+
.Select("new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)");
38+
39+
var combined = grouping1.ToDynamicArray().Concat(grouping2.ToDynamicArray()).AsQueryable();
40+
var ordered = combined.OrderBy("Product").ToDynamicList();
41+
42+
// Assert
43+
ordered.Should().HaveCount(6);
44+
}
45+
46+
[Fact]
47+
public void DynamicGetMemberBinder_Test2()
48+
{
49+
// Arrange
50+
var dynamicData = new[] { 1, 2 }
51+
.AsQueryable()
52+
.Select("new { it as Value }")
53+
.ToDynamicArray();
54+
55+
// Act
56+
var dynamicResult = dynamicData
57+
.AsQueryable()
58+
.Select("Value")
59+
.ToDynamicArray();
60+
61+
// Assert
62+
dynamicResult.Should().HaveCount(2);
63+
}
64+
}

0 commit comments

Comments
 (0)