protected override Expression VisitLambda <T>(Expression <T> node) { if (node.Body is NewExpression && ((NewExpression)node.Body).Type == typeof(DynamicObjectClass)) { var e = node.Body as NewExpression; var properties = new List <DynamicProperty>(e.Arguments.Count); var expressions = new List <Expression>(e.Arguments.Count); foreach (NewExpression newEx in e.Arguments) { var name = ((ConstantExpression)newEx.Arguments.First()).Value as string; var parameter = ((UnaryExpression)newEx.Arguments.Skip(1).First()).Operand; properties.Add(new DynamicProperty(name, parameter.Type)); expressions.Add(parameter); } Type type = DynamicExpression.CreateClass(properties); MemberBinding[] bindings = new MemberBinding[properties.Count]; for (int i = 0; i < bindings.Length; i++) { bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]); } var membInit = Expression.MemberInit(Expression.New(type), bindings); var typeOfTArgs = typeof(T).GetGenericArguments(); var funcTType = typeof(Func <,>).MakeGenericType(new[] { typeOfTArgs.First(), type }); var mi = typeof(Expression).GetMethods().FirstOrDefault(x => x.Name == "Lambda" && x.ContainsGenericParameters); MethodInfo genericMethod = mi.MakeGenericMethod(new[] { funcTType }); var lambda = genericMethod.Invoke(null, new object[] { membInit, node.Parameters.ToArray() }) as Expression; return(lambda); } return(base.VisitLambda <T>(node)); }
private static object PrepareAggregate <T>(IQueryable <T> queryable, Query q) { var aggregates = q.Aggregates; if (aggregates != null && aggregates.Any()) { var objProps = new Dictionary <DynamicProperty, object>(); var groups = aggregates.GroupBy(g => g.ColumnName); Type type = null; foreach (var group in groups) { var fieldProps = new Dictionary <DynamicProperty, object>(); foreach (var aggregate in group) { var prop = typeof(T).GetProperty(aggregate.ColumnName); var param = Expression.Parameter(typeof(T), "s"); var selector = aggregate.Aggregate == "count" && (Nullable.GetUnderlyingType(prop.PropertyType) != null) ? Expression.Lambda(Expression.NotEqual(Expression.MakeMemberAccess(param, prop), Expression.Constant(null, prop.PropertyType)), param) : Expression.Lambda(Expression.MakeMemberAccess(param, prop), param); var mi = aggregate.MethodInfo(typeof(T)); if (mi == null) { continue; } var val = queryable.Provider.Execute(Expression.Call(null, mi, aggregate.Aggregate == "count" && (Nullable.GetUnderlyingType(prop.PropertyType) == null) ? new[] { queryable.Expression } : new[] { queryable.Expression, Expression.Quote(selector) })); fieldProps.Add(new DynamicProperty(aggregate.Aggregate, typeof(object)), val); } type = DynamicExpression.CreateClass(fieldProps.Keys); var fieldObj = Activator.CreateInstance(type); foreach (var p in fieldProps.Keys) { type.GetProperty(p.Name).SetValue(fieldObj, fieldProps[p], null); } objProps.Add(new DynamicProperty(group.Key, fieldObj.GetType()), fieldObj); } type = DynamicExpression.CreateClass(objProps.Keys); var obj = Activator.CreateInstance(type); foreach (var p in objProps.Keys) { type.GetProperty(p.Name).SetValue(obj, objProps[p], null); } return(obj); } else { return(null); } }
public static object Aggregate <T>(this IQueryable <T> queryable, IEnumerable <Aggregator> aggregates) { if (aggregates == null) { return(null); } var aggregators = aggregates as Aggregator[] ?? aggregates.ToArray(); if (!aggregators.Any()) { return(null); } var objProps = new Dictionary <DynamicProperty, object>(); var groups = aggregators.GroupBy(g => g.Field); Type type; foreach (var group in groups) { var fieldProps = new Dictionary <DynamicProperty, object>(); foreach (var aggregate in group) { var prop = typeof(T).GetProperty(aggregate.Field); if (prop == null) { throw new InvalidOperationException($"{aggregate.Field} Property does not exists!"); } var param = Expression.Parameter(typeof(T), "s"); var selector = aggregate.Aggregate == "count" && Nullable.GetUnderlyingType(prop.PropertyType) != null ? Expression.Lambda( Expression.NotEqual(Expression.MakeMemberAccess(param, prop), Expression.Constant(null, prop.PropertyType)), param) : Expression.Lambda(Expression.MakeMemberAccess(param, prop), param); var mi = aggregate.MethodInfo(typeof(T)); if (mi == null) { continue; } var val = queryable.Provider.Execute(Expression.Call(null, mi, aggregate.Aggregate == "count" && Nullable.GetUnderlyingType(prop.PropertyType) == null ? new[] { queryable.Expression } : new[] { queryable.Expression, Expression.Quote(selector) })); fieldProps.Add(new DynamicProperty(aggregate.Aggregate, typeof(object)), val); } type = DynamicExpression.CreateClass(fieldProps.Keys); var fieldObj = Activator.CreateInstance(type); foreach (var p in fieldProps.Keys) { type.GetProperty(p.Name).SetValue(fieldObj, fieldProps[p], null); } objProps.Add(new DynamicProperty(group.Key, fieldObj.GetType()), fieldObj); } type = DynamicExpression.CreateClass(objProps.Keys); var obj = Activator.CreateInstance(type); foreach (var p in objProps.Keys) { type.GetProperty(p.Name).SetValue(obj, objProps[p], null); } return(obj); }