public InlineFlattenedTypeVisitor(NewExpression anonymousConstructor, ParameterExpression converted, ParameterExpression initial, AnonymousTypeFlattener flattener)
     : base(anonymousConstructor)
 {
     _initial   = initial;
     _converted = converted;
     _flattener = flattener;
 }
            protected internal override QueryOperator VisitSelect(SelectOperator op)
            {
                var src      = VisitAndConvert <MonadMember>(op.Source);
                var selector = Visit(op.Selector);

                if (TryCast <SelectOperator>(src, OperatorType.Select, out SelectOperator select1) &&
                    TryExtractNullaryLambdaBody <LambdaExpression>(select1.Selector, ExpressionType.Lambda, out LambdaExpression selector1) &&
                    TryGetNewAnonymousType(selector1.Body, out NewExpression anonCtor1) &&
                    TryExtractNullaryLambdaBody <LambdaExpression>(selector, ExpressionType.Lambda, out LambdaExpression selector2))
                {
                    if (TryGetNewAnonymousType(selector2.Body, out NewExpression anonCtor2))
                    {
                        if (anonCtor2.Members.Count > 0 && anonCtor2.Arguments[0] == selector2.Parameters[0])
                        {
                            var newArgs = new Expression[anonCtor2.Members.Count];
                            newArgs[0] = anonCtor1;

                            for (var i = 1; i < newArgs.Length; i++)
                            {
                                var visitor = new ValidateMemberAccessesAndInlineVisitor(anonCtor1, selector1.Parameters[0], selector2.Parameters[0]);
                                newArgs[i] = visitor.Visit(anonCtor2.Arguments[i]);
                                if (!visitor.Valid)
                                {
                                    return(UpdateSelect(op, src, selector));
                                }
                            }

                            var updated = anonCtor2.Update(newArgs);
                            var newBody =
                                DefaultQueryExpressionFactory.Instance.LambdaAbstraction(
                                    Expression.Lambda(Expression.Lambda(updated, selector1.Parameters[0])),
                                    Array.Empty <QueryTree>()
                                    );
                            return
                                (op.QueryExpressionFactory.Select(
                                     op.ElementType,
                                     select1.InputElementType,
                                     select1.Source,
                                     newBody
                                     ));
                        }
                    }
                    else
                    {
                        var flatteningValidationVisitor = new ValidateMemberAccessVisitor(anonCtor1, selector2.Parameters[0]);
                        flatteningValidationVisitor.Visit(selector2.Body);
                        if (flatteningValidationVisitor.Valid)
                        {
                            var flattener = new AnonymousTypeFlattener(anonCtor1);
                            if (flattener.TryConstruct(out NewExpression c))
                            {
                                var t                 = c.Type;
                                var newParam          = Expression.Parameter(t);
                                var flatteningVisitor = new InlineFlattenedTypeVisitor(anonCtor1, newParam, selector2.Parameters[0], flattener);
                                var f                 = flatteningVisitor.Visit(selector2.Body);

                                var child =
                                    select1.QueryExpressionFactory.Select(
                                        t,
                                        select1.InputElementType,
                                        select1.Source,
                                        DefaultQueryExpressionFactory.Instance.LambdaAbstraction(
                                            Expression.Lambda(Expression.Lambda(c, selector1.Parameters[0])),
                                            Array.Empty <QueryTree>()
                                            )
                                        );

                                return
                                    (op.QueryExpressionFactory.Select(
                                         op.ElementType,
                                         t,
                                         child,
                                         DefaultQueryExpressionFactory.Instance.LambdaAbstraction(
                                             Expression.Lambda(Expression.Lambda(f, newParam)),
                                             Array.Empty <QueryTree>()
                                             )
                                         ));
                            }
                        }
                    }
                }

                return(UpdateSelect(op, src, selector));
            }