private static NewExpression BuildNewExpression(ParameterExpression rootParameter, IReadOnlyDictionary <PropertyPath, ODataSelectColumnExpression> mapping) { // all paths longer than length 1 get grouped together and mapped to their own expression (this lets us support an arbitrary number of selected columns) var nestedProperties = mapping.Where(kvp => kvp.Key.Count > 1).ToArray(); var nestedExpression = nestedProperties.Length > 0 ? BuildNewExpression(rootParameter, nestedProperties.ToDictionary(kvp => kvp.Key.Skip(1).ToArray().As <PropertyPath>(), kvp => kvp.Value, PathComparer)) : Expression.Constant(false).As <Expression>(); // gather all argument expressions which will be used to initialize the type var arguments = ProjectionTypeProperties.Take(ProjectionTypeProperties.Count - 1) .Select(prop => { ODataSelectColumnExpression selectColumn; if (!mapping.TryGetValue(new[] { prop }, out selectColumn)) { return(Expression.Constant(false)); } var selectColumnPropertyPath = Traverse.Along(selectColumn.Expression, c => c.Expression) .Select(m => m.Member) .Reverse(); var expression = selectColumnPropertyPath.Aggregate(rootParameter.As <Expression>(), (acc, pi) => Expression.MakeMemberAccess(acc, pi)); return(expression); }) .ToList(); arguments.Add(nestedExpression); // build the new expression var parameterizedType = ProjectionType.MakeGenericType(arguments.Select(a => a.Type).ToArray()); var newExpression = Expression.New( parameterizedType.GetConstructors().Single(), arguments, members: parameterizedType.GetProperties(BindingFlags.Public | BindingFlags.Instance) ); return(newExpression); }
/// <summary> /// Initializes a new assignment expression. /// </summary> /// <param name="left">The left operand of the assignment.</param> /// <param name="right">The right operand of the assignment.</param> /// <exception cref="ArgumentException"><paramref name="right"/> is not assignable to <paramref name="left"/>.</exception> public NullCoalescingAssignmentExpression(ParameterExpression left, Expression right) : this(left.As <Expression>(), right) { }