@@ -186,6 +186,67 @@ interface IEnumerableSignatures
186186 void ToList ( ) ;
187187 }
188188
189+ interface IQueryableSignatures
190+ {
191+ void All ( bool predicate ) ;
192+ void Any ( ) ;
193+ void Any ( bool predicate ) ;
194+ void Average ( decimal ? selector ) ;
195+ void Average ( decimal selector ) ;
196+ void Average ( double ? selector ) ;
197+ void Average ( double selector ) ;
198+ void Average ( float ? selector ) ;
199+ void Average ( float selector ) ;
200+ void Average ( int ? selector ) ;
201+ void Average ( int selector ) ;
202+ void Average ( long ? selector ) ;
203+ void Average ( long selector ) ;
204+ void Count ( ) ;
205+ void Count ( bool predicate ) ;
206+ void DefaultIfEmpty ( ) ;
207+ void DefaultIfEmpty ( object defaultValue ) ;
208+ void Distinct ( ) ;
209+ void First ( bool predicate ) ;
210+ void FirstOrDefault ( bool predicate ) ;
211+ void GroupBy ( object keySelector ) ;
212+ void GroupBy ( object keySelector , object elementSelector ) ;
213+ void Last ( bool predicate ) ;
214+ void LastOrDefault ( bool predicate ) ;
215+ void Max ( object selector ) ;
216+ void Min ( object selector ) ;
217+ void OrderBy ( object selector ) ;
218+ void OrderByDescending ( object selector ) ;
219+ void Select ( object selector ) ;
220+ void SelectMany ( object selector ) ;
221+ void Single ( bool predicate ) ;
222+ void SingleOrDefault ( bool predicate ) ;
223+ void Skip ( int count ) ;
224+ void SkipWhile ( bool predicate ) ;
225+ void Sum ( decimal ? selector ) ;
226+ void Sum ( decimal selector ) ;
227+ void Sum ( double ? selector ) ;
228+ void Sum ( double selector ) ;
229+ void Sum ( float ? selector ) ;
230+ void Sum ( float selector ) ;
231+ void Sum ( int ? selector ) ;
232+ void Sum ( int selector ) ;
233+ void Sum ( long ? selector ) ;
234+ void Sum ( long selector ) ;
235+ void Take ( int count ) ;
236+ void TakeWhile ( bool predicate ) ;
237+ void ThenBy ( object selector ) ;
238+ void ThenByDescending ( object selector ) ;
239+ void Where ( bool predicate ) ;
240+
241+ // Executors
242+ void First ( ) ;
243+ void FirstOrDefault ( ) ;
244+ void Last ( ) ;
245+ void LastOrDefault ( ) ;
246+ void Single ( ) ;
247+ void SingleOrDefault ( ) ;
248+ }
249+
189250 // These shorthands have different name than actual type and therefore not recognized by default from the _predefinedTypes
190251 static readonly Dictionary < string , Type > _predefinedTypesShorthands = new Dictionary < string , Type >
191252 {
@@ -575,13 +636,7 @@ Expression ParseIn()
575636
576637 args = new [ ] { right , left } ;
577638
578- Type callType = typeof ( Enumerable ) ;
579- if ( ! typeof ( IQueryable ) . IsAssignableFrom ( right . Type ) && ContainsMethod ( typeof ( Queryable ) , containsSignature . Name , false , args ) )
580- {
581- callType = typeof ( Queryable ) ;
582- }
583-
584- accumulate = Expression . Call ( callType , containsSignature . Name , typeArgs , args ) ;
639+ accumulate = Expression . Call ( typeof ( Enumerable ) , containsSignature . Name , typeArgs , args ) ;
585640 }
586641 else
587642 {
@@ -1641,7 +1696,7 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
16411696
16421697 if ( methodName == "Contains" || methodName == "Skip" || methodName == "Take" )
16431698 {
1644- //for any method that acts on the parent element type, we need to specify the outerIt as scope.
1699+ // for any method that acts on the parent element type, we need to specify the outerIt as scope.
16451700 _it = outerIt ;
16461701 }
16471702 else
@@ -1654,13 +1709,19 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
16541709 _it = outerIt ;
16551710 _parent = oldParent ;
16561711
1657- if ( FindMethod ( typeof ( IEnumerableSignatures ) , methodName , false , args , out MethodBase signature ) != 1 )
1712+ if ( ! ContainsMethod ( typeof ( IEnumerableSignatures ) , methodName , false , args ) )
16581713 {
16591714 throw ParseError ( errorPos , Res . NoApplicableAggregate , methodName ) ;
16601715 }
16611716
1717+ Type callType = typeof ( Enumerable ) ;
1718+ if ( isQueryable && ContainsMethod ( typeof ( IQueryableSignatures ) , methodName , false , args ) )
1719+ {
1720+ callType = typeof ( Queryable ) ;
1721+ }
1722+
16621723 Type [ ] typeArgs ;
1663- if ( new [ ] { "Min" , "Max" , "Select" , "OrderBy" , "OrderByDescending" , "ThenBy" , "ThenByDescending" , "GroupBy" } . Contains ( signature . Name ) )
1724+ if ( new [ ] { "Min" , "Max" , "Select" , "OrderBy" , "OrderByDescending" , "ThenBy" , "ThenByDescending" , "GroupBy" } . Contains ( methodName ) )
16641725 {
16651726 if ( args . Length == 2 )
16661727 {
@@ -1671,7 +1732,7 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
16711732 typeArgs = new [ ] { elementType , args [ 0 ] . Type } ;
16721733 }
16731734 }
1674- else if ( signature . Name == "SelectMany" )
1735+ else if ( methodName == "SelectMany" )
16751736 {
16761737 var type = Expression . Lambda ( args [ 0 ] , innerIt ) . Body . Type ;
16771738 var interfaces = type . GetInterfaces ( ) . Union ( new [ ] { type } ) ;
@@ -1690,7 +1751,7 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
16901751 }
16911752 else
16921753 {
1693- if ( new [ ] { "Contains" , "Take" , "Skip" , "DefaultIfEmpty" } . Contains ( signature . Name ) )
1754+ if ( new [ ] { "Contains" , "Take" , "Skip" , "DefaultIfEmpty" } . Contains ( methodName ) )
16941755 {
16951756 args = new [ ] { instance , args [ 0 ] } ;
16961757 }
@@ -1707,16 +1768,7 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
17071768 }
17081769 }
17091770
1710- Type callType = typeof ( Enumerable ) ;
1711- if ( isQueryable )
1712- {
1713- if ( ContainsMethod ( typeof ( Queryable ) , signature . Name , false , args ) )
1714- {
1715- callType = typeof ( Queryable ) ;
1716- }
1717- }
1718-
1719- return Expression . Call ( callType , signature . Name , typeArgs , args ) ;
1771+ return Expression . Call ( callType , methodName , typeArgs , args ) ;
17201772 }
17211773
17221774 Expression [ ] ParseArgumentList ( )
0 commit comments