Example #1
0
        /// <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));
        }