Skip to content

Commit 06f3c6b

Browse files
committed
Add support for all numeric data types to summary aggregate functions
Collapse aggregates into one basic function
1 parent aedf607 commit 06f3c6b

File tree

2 files changed

+75
-15
lines changed

2 files changed

+75
-15
lines changed

Griddly.Mvc/DynamicLinq.cs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,41 @@ public static IQueryable Where(this IQueryable source, string predicate, params
3232
source.Expression, Expression.Quote(lambda)));
3333
}
3434

35-
public static IQueryable Select(this IQueryable source, string selector, params object[] values)
35+
//public static IQueryable Select(this IQueryable source, string selector, params object[] values)
36+
//{
37+
// if (source == null) throw new ArgumentNullException("source");
38+
// if (selector == null) throw new ArgumentNullException("selector");
39+
// LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);
40+
// return source.Provider.CreateQuery(
41+
// Expression.Call(
42+
// typeof(Queryable), "Select",
43+
// new Type[] { source.ElementType, lambda.Body.Type },
44+
// source.Expression, Expression.Quote(lambda)));
45+
//}
46+
47+
// https://code.google.com/p/dynamic-linq/
48+
public static IQueryable Select(this IQueryable source, Type type, string selector, params object[] values)
3649
{
3750
if (source == null) throw new ArgumentNullException("source");
3851
if (selector == null) throw new ArgumentNullException("selector");
39-
LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);
52+
LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, type, selector, values);
4053
return source.Provider.CreateQuery(
4154
Expression.Call(
4255
typeof(Queryable), "Select",
4356
new Type[] { source.ElementType, lambda.Body.Type },
4457
source.Expression, Expression.Quote(lambda)));
4558
}
4659

60+
public static IQueryable Select(this IQueryable source, string selector, params object[] values)
61+
{
62+
return Select(source, null, selector, values);
63+
}
64+
65+
public static IQueryable<T> Select<T>(this IQueryable source, string selector, params object[] values)
66+
{
67+
return Select(source, typeof(T), selector, values) as IQueryable<T>;
68+
}
69+
4770
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values)
4871
{
4972
return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);
@@ -123,6 +146,52 @@ public static int Count(this IQueryable source)
123146
typeof(Queryable), "Count",
124147
new Type[] { source.ElementType }, source.Expression));
125148
}
149+
150+
// http://stackoverflow.com/questions/17490080/how-to-do-a-sum-using-dynamic-linq
151+
public static object Aggregate(this IQueryable source, string function, string member)
152+
{
153+
if (source == null) throw new ArgumentNullException("source");
154+
if (member == null) throw new ArgumentNullException("member");
155+
156+
// Properties
157+
PropertyInfo property = source.ElementType.GetProperty(member);
158+
ParameterExpression parameter = Expression.Parameter(source.ElementType, "s");
159+
Expression selector = Expression.Lambda(Expression.MakeMemberAccess(parameter, property), parameter);
160+
// We've tried to find an expression of the type Expression<Func<TSource, TAcc>>,
161+
// which is expressed as ( (TSource s) => s.Price );
162+
163+
var methods = typeof(Queryable).GetMethods().Where(x => x.Name == function);
164+
165+
// Method
166+
MethodInfo aggregateMethod = typeof(Queryable).GetMethods().SingleOrDefault(
167+
m => m.Name == function
168+
&& m.ReturnType == property.PropertyType // should match the type of the property
169+
&& m.IsGenericMethod);
170+
171+
// Sum, Average
172+
if (aggregateMethod != null)
173+
{
174+
return source.Provider.Execute(
175+
Expression.Call(
176+
null,
177+
aggregateMethod.MakeGenericMethod(new[] { source.ElementType }),
178+
new[] { source.Expression, Expression.Quote(selector) }));
179+
}
180+
// Min, Max
181+
else
182+
{
183+
aggregateMethod = typeof(Queryable).GetMethods().SingleOrDefault(
184+
m => m.Name == function
185+
&& m.GetGenericArguments().Length == 2
186+
&& m.IsGenericMethod);
187+
188+
return source.Provider.Execute(
189+
Expression.Call(
190+
null,
191+
aggregateMethod.MakeGenericMethod(new[] { source.ElementType, property.PropertyType }),
192+
new[] { source.Expression, Expression.Quote(selector) }));
193+
}
194+
}
126195
}
127196

128197
public abstract class DynamicClass

Griddly.Mvc/GriddlyResult.cs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
using System;
1+
using Griddly.Mvc.Linq.Dynamic;
2+
using System;
23
using System.Collections;
34
using System.Collections.Generic;
45
using System.Collections.Specialized;
56
using System.Linq;
67
using System.Linq.Expressions;
78
using System.Reflection;
8-
using System.Text;
99
using System.Web.Helpers;
1010
using System.Web.Mvc;
11-
using Griddly.Mvc.Linq.Dynamic;
1211

1312
namespace Griddly.Mvc
1413
{
@@ -224,21 +223,13 @@ public virtual void PopulateSummaryValues(GriddlySettings<T> settings)
224223
switch (c.SummaryFunction.Value)
225224
{
226225
case SummaryAggregateFunction.Sum:
227-
c.SummaryValue = _result.Select(c.ExpressionString).Cast<decimal?>().Sum();
228-
229-
break;
230226
case SummaryAggregateFunction.Average:
231-
c.SummaryValue = _result.Select(c.ExpressionString).Cast<decimal?>().Average();
232-
233-
break;
234227
case SummaryAggregateFunction.Min:
235-
c.SummaryValue = _result.Select(c.ExpressionString).Cast<decimal?>().Min();
236-
237-
break;
238228
case SummaryAggregateFunction.Max:
239-
c.SummaryValue = _result.Select(c.ExpressionString).Cast<decimal?>().Max();
229+
c.SummaryValue = _result.Aggregate(c.SummaryFunction.Value.ToString(), c.ExpressionString);
240230

241231
break;
232+
242233
default:
243234
throw new InvalidOperationException(string.Format("Unknown summary function {0} for column {1}.", c.SummaryFunction, c.ExpressionString));
244235
}

0 commit comments

Comments
 (0)