1+ using System . Data ;
2+ using System . Linq . Dynamic . Core . Tests . TestHelpers ;
3+ using FluentAssertions ;
4+ using Xunit ;
5+
6+ namespace System . Linq . Dynamic . Core . Tests ;
7+
8+ public class DynamicGetMemberBinderTests
9+ {
10+ public class SalesData
11+ {
12+ public string Region { get ; set ; } = null ! ;
13+
14+ public string Product { get ; set ; } = null ! ;
15+
16+ public string Sales { get ; set ; } = null ! ;
17+ }
18+
19+ public class GroupedSalesData
20+ {
21+ public string Region { get ; set ; } = null ! ;
22+ public string ? Product { get ; set ; }
23+ public int TotalSales { get ; set ; }
24+ public int GroupLevel { get ; set ; }
25+ }
26+
27+ [ Fact ]
28+ public void DynamicGetMemberBinder_SelectOnArrayWithComplexObjects ( )
29+ {
30+ // Arrange
31+ var rows = new SalesData [ ]
32+ {
33+ new ( ) { Region = "North" , Product = "Widget" , Sales = "100" } ,
34+ new ( ) { Region = "North" , Product = "Gadget" , Sales = "150" } ,
35+ new ( ) { Region = "South" , Product = "Widget" , Sales = "200" } ,
36+ new ( ) { Region = "South" , Product = "Gadget" , Sales = "100" } ,
37+ new ( ) { Region = "North" , Product = "Widget" , Sales = "50" }
38+ } . AsQueryable ( ) ;
39+
40+ // Act
41+ var grouping1 = rows
42+ . GroupBy ( "new (Region, Product)" )
43+ . Select ( "new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)" ) ;
44+
45+ var grouping2 = rows
46+ . GroupBy ( "Region" )
47+ . Select ( "new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)" ) ;
48+
49+ var combined = grouping1 . ToDynamicArray ( ) . Concat ( grouping2 . ToDynamicArray ( ) ) . AsQueryable ( ) ;
50+ var ordered = combined . OrderBy ( "Product" ) . ToDynamicList ( ) ;
51+
52+ // Assert
53+ ordered . Should ( ) . HaveCount ( 6 ) ;
54+ }
55+
56+ [ Fact ]
57+ public void DynamicGetMemberBinder_SelectTypeOnArrayWithComplexObjects ( )
58+ {
59+ // Arrange
60+ var rows = new SalesData [ ]
61+ {
62+ new ( ) { Region = "North" , Product = "Widget" , Sales = "100" } ,
63+ new ( ) { Region = "North" , Product = "Gadget" , Sales = "150" } ,
64+ new ( ) { Region = "South" , Product = "Widget" , Sales = "200" } ,
65+ new ( ) { Region = "South" , Product = "Gadget" , Sales = "100" } ,
66+ new ( ) { Region = "North" , Product = "Widget" , Sales = "50" }
67+ } . AsQueryable ( ) ;
68+
69+ // Act
70+ var grouping1 = rows
71+ . GroupBy ( "new (Region, Product)" )
72+ . Select < GroupedSalesData > ( "new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)" ) ;
73+
74+ var grouping2 = rows
75+ . GroupBy ( "Region" )
76+ . Select < GroupedSalesData > ( "new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)" ) ;
77+
78+ var combined = grouping1 . Concat ( grouping2 ) . AsQueryable ( ) ;
79+ var ordered = combined . OrderBy ( "Product" ) . ToDynamicList ( ) ;
80+
81+ // Assert
82+ ordered . Should ( ) . HaveCount ( 6 ) ;
83+ }
84+
85+ [ SkipIfGitHubActionsFact ]
86+ public void DynamicGetMemberBinder_SelectOnDataTable ( )
87+ {
88+ // Arrange
89+ var dataTable = new DataTable ( ) ;
90+ dataTable . Columns . Add ( "Region" , typeof ( string ) ) ;
91+ dataTable . Columns . Add ( "Product" , typeof ( string ) ) ;
92+ dataTable . Columns . Add ( "Sales" , typeof ( int ) ) ;
93+
94+ dataTable . Rows . Add ( "North" , "Apples" , 100 ) ;
95+ dataTable . Rows . Add ( "North" , "Oranges" , 150 ) ;
96+ dataTable . Rows . Add ( "South" , "Apples" , 200 ) ;
97+ dataTable . Rows . Add ( "South" , "Oranges" , 250 ) ;
98+
99+ var rows = dataTable . Rows . Cast < DataRow > ( ) . AsQueryable ( ) ;
100+
101+ // Act
102+ var grouping1 = rows
103+ . GroupBy ( "new (Region, Product)" )
104+ . Select ( "new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)" ) ;
105+
106+ var grouping2 = rows
107+ . GroupBy ( "Region" )
108+ . Select ( "new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)" ) ;
109+
110+ var combined = grouping1 . ToDynamicArray ( ) . Concat ( grouping2 . ToDynamicArray ( ) ) . AsQueryable ( ) ;
111+ var ordered = combined . OrderBy ( "Product" ) . ToDynamicList ( ) ;
112+
113+ // Assert
114+ ordered . Should ( ) . HaveCount ( 6 ) ;
115+ }
116+
117+ [ SkipIfGitHubActionsFact ]
118+ public void DynamicGetMemberBinder_SelectTypeOnDataTable ( )
119+ {
120+ // Arrange
121+ var dataTable = new DataTable ( ) ;
122+ dataTable . Columns . Add ( "Region" , typeof ( string ) ) ;
123+ dataTable . Columns . Add ( "Product" , typeof ( string ) ) ;
124+ dataTable . Columns . Add ( "Sales" , typeof ( int ) ) ;
125+
126+ dataTable . Rows . Add ( "North" , "Apples" , 100 ) ;
127+ dataTable . Rows . Add ( "North" , "Oranges" , 150 ) ;
128+ dataTable . Rows . Add ( "South" , "Apples" , 200 ) ;
129+ dataTable . Rows . Add ( "South" , "Oranges" , 250 ) ;
130+
131+ var rows = dataTable . Rows . Cast < DataRow > ( ) . AsQueryable ( ) ;
132+
133+ // Act
134+ var grouping1 = rows
135+ . GroupBy ( "new (Region, Product)" )
136+ . Select < GroupedSalesData > ( "new (Key.Region as Region, Key.Product as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 0 as GroupLevel)" ) ;
137+
138+ var grouping2 = rows
139+ . GroupBy ( "Region" )
140+ . Select < GroupedSalesData > ( "new (Key as Region, null as Product, Sum(Convert.ToInt32(Sales)) as TotalSales, 1 as GroupLevel)" ) ;
141+
142+ var combined = grouping1 . ToDynamicArray ( ) . Concat ( grouping2 . ToDynamicArray ( ) ) . AsQueryable ( ) ;
143+ var ordered = combined . OrderBy ( "Product" ) . ToDynamicList ( ) ;
144+
145+ // Assert
146+ ordered . Should ( ) . HaveCount ( 6 ) ;
147+ }
148+
149+ [ Fact ]
150+ public void DynamicGetMemberBinder_SelectOnArrayWithIntegers ( )
151+ {
152+ // Arrange
153+ var dynamicData = new [ ] { 1 , 2 }
154+ . AsQueryable ( )
155+ . Select ( "new { it * 2 as Value }" )
156+ . ToDynamicArray ( )
157+ . AsQueryable ( ) ;
158+
159+ // Act
160+ var dynamicResult1 = dynamicData
161+ . Select ( "Value" )
162+ . ToDynamicArray ( ) ;
163+
164+ var dynamicResult2 = dynamicData
165+ . Select ( "Value" )
166+ . ToDynamicArray < int > ( ) ;
167+
168+ // Assert
169+ dynamicResult1 . Should ( ) . HaveCount ( 2 ) ;
170+ dynamicResult2 . Should ( ) . BeEquivalentTo ( [ 2 , 4 ] ) ;
171+ }
172+ }
0 commit comments