/// <summary> /// Rewrites a projection that produces a single member to a projection that produces a member of type ColumnSettings. /// </summary> /// <param name="expression">Projector.</param> /// <returns>A modified expression if projection produces a single member; otherwise the same expression.</returns> public override Expression Rewrite(Expression expression) { var lambda = (LambdaExpression)expression; var compositeTypeVisitor = new CompositeTypeVisitor(); compositeTypeVisitor.Visit(lambda); if (compositeTypeVisitor.IsProjectingACompositeType) { return(expression); } Expression projection = null; _expressions = new List <Expression>(); try { Visit(lambda.Body); if (_expressions.Count == 1) { MemberExpression memberExp = (MemberExpression)_expressions[0]; string propertyName = memberExp.Member.Name; var columnSettings = ((ColumnSettings)typeof(ColumnSettings) .GetMethod("Build") .MakeGenericMethod(new Type[] { lambda.Body.Type }) .Invoke(null, new object[] { Expression.Lambda(lambda.Body) })) .Name(propertyName); projection = Expression.Constant(columnSettings, typeof(ColumnSettings)); } else if (_expressions.Count > 1) { throw new InvalidProjectionException("There are multiple members across the projection. Ensure you project a single member, otherwise wrap it using a new operator.", lambda.Body); } } finally { _expressions = null; } if (projection == null) { return(expression); } return(Expression.Lambda(projection, lambda.Parameters)); }
/// <summary> /// Checks whether the projection is valid or not. A projection is valid if it's a flat projection and references at least one time the projector's parameter. /// </summary> /// <param name="expression">Projector.</param> public void Validate(Expression expression) { // Checks if the lambda's expression parameter is referenced within the projection var paramProjectionValidator = new ParameterReferencesValidator(); paramProjectionValidator.Validate(expression); // Determines if the projection denotes a composite type or not var compositeTypeVisitor = new CompositeTypeVisitor(); compositeTypeVisitor.Visit(expression); if (!compositeTypeVisitor.IsProjectingACompositeType) { // It's a single member projection, so it checks if the ColumnSettings has a name set var columnSettingsProjValidator = new ColumnSettingsNameValidator(); columnSettingsProjValidator.Validate(expression); } else { var flatProjectionValidator = new FlatProjectionValidator(); flatProjectionValidator.Validate(expression); } }