/// <summary> /// Create a <see cref="LambdaExpression"/> such as: Expression{Func{Sales, keyType}} projectionLambda = s => new KeyType(Amount = s.Amount, Id=s.Id). /// </summary> /// <param name="selectStatements">The selected statements creating the key of the group-by operation.</param> /// <param name="keyType">The type of the key of the group-by operation.</param> /// <param name="propertiesToGroupByExpressions">List of expressions to the properties to group by.</param> /// <returns><see cref="LambdaExpression"/>.</returns> private LambdaExpression GetGroupByProjectionLambda(string[] selectStatements, Type keyType, LambdaExpression[] propertiesToGroupByExpressions) { Contract.Assert(keyType != null); Contract.Assert(selectStatements != null && selectStatements.Any()); ParameterExpression entityParam; if (propertiesToGroupByExpressions != null && propertiesToGroupByExpressions.Any()) { entityParam = propertiesToGroupByExpressions.First().Parameters.First(); } else { entityParam = Expression.Parameter(this.Context.ElementClrType, "e"); } var bindings = new List <MemberAssignment>(); for (int i = 0; i < selectStatements.Length; i++) { var statement = selectStatements[i]; Expression selectedProperyExpression = null; if (propertiesToGroupByExpressions != null) { selectedProperyExpression = propertiesToGroupByExpressions[i].Body; } string samplingMethod, alias, samplingProperty; GroupByImplementation.GetSamplingMethod(statement, out samplingMethod, out alias, out samplingProperty); if (samplingMethod == null) { var prop = statement; if (prop.Contains('/')) { prop = statement.Substring(0, prop.IndexOf('/')); } prop = prop.TrimMethodCall().Split(' ').First(); var mi = keyType.GetMember(prop).First(); bindings.Add(Expression.Bind(mi, ApplyImplementationBase.GetPropertyExpression(keyType, statement, entityParam, selectedProperyExpression))); } else { string prop = alias; if (statement.Contains('/')) { prop = statement.Substring(0, statement.IndexOf('/')); } var mi = keyType.GetMember(prop).First(); var propertyType = GetPropertyInfo(this.Context.ElementClrType, statement).Last().PropertyType; var implementation = SamplingMethodsImplementations.GetAggregationImplementation(samplingMethod); MethodInfo method = implementation.GetSamplingProcessingMethod(propertyType); var aggregationParamsExpressions = GetAggregationArgumentsExpressions(samplingMethod, method); bindings.Add(Expression.Bind(mi, ApplyImplementationBase.GetComputedPropertyExpression(keyType, statement, entityParam, method, selectedProperyExpression, aggregationParamsExpressions))); } } var body = Expression.MemberInit(Expression.New(keyType), bindings); return(Expression.Lambda(body, entityParam)); }