Skip to content

Commit ad44be5

Browse files
jogibear9988StefH
authored andcommitted
Bugfix DynamicLinq when using IQueryable (#116)
* Bugfix DyanmicLinq when using IQueryable * bugfix ExpressionParser for IQueryable * Small update to ParseAggregate
1 parent 0f5a0be commit ad44be5

File tree

1 file changed

+74
-22
lines changed

1 file changed

+74
-22
lines changed

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

+74-22
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)