public GroupJoinExpressionNode(
            MethodCallExpressionParseInfo parseInfo,
            Expression innerSequence,
            LambdaExpression outerKeySelector,
            LambdaExpression innerKeySelector,
            LambdaExpression resultSelector)
            : base(parseInfo)
        {
            ArgumentUtility.CheckNotNull("innerSequence", innerSequence);
            ArgumentUtility.CheckNotNull("outerKeySelector", outerKeySelector);
            ArgumentUtility.CheckNotNull("innerKeySelector", innerKeySelector);
            ArgumentUtility.CheckNotNull("resultSelector", resultSelector);

            if (outerKeySelector.Parameters.Count != 1)
            {
                throw new ArgumentException("Outer key selector must have exactly one parameter.", "outerKeySelector");
            }
            if (innerKeySelector.Parameters.Count != 1)
            {
                throw new ArgumentException("Inner key selector must have exactly one parameter.", "innerKeySelector");
            }
            if (resultSelector.Parameters.Count != 2)
            {
                throw new ArgumentException("Result selector must have exactly two parameters.", "resultSelector");
            }

            var joinResultSelector = Expression.Lambda(Expression.Constant(null), outerKeySelector.Parameters[0],
                                                       innerKeySelector.Parameters[0]);

#pragma warning disable 618
            JoinExpressionNode = new JoinExpressionNode(parseInfo, innerSequence, outerKeySelector, innerKeySelector,
                                                        joinResultSelector);
#pragma warning restore 618
            ParsedExpression      = parseInfo.ParsedExpression;
            InnerSequence         = innerSequence;
            OuterKeySelector      = outerKeySelector;
            InnerKeySelector      = innerKeySelector;
            ResultSelector        = resultSelector;
            _cachedResultSelector = new ResolvedExpressionCache <Expression>(this);
        }
        protected override void ApplyNodeSpecificSemantics(QueryModel queryModel,
                                                           ClauseGenerationContext clauseGenerationContext)
        {
            ArgumentUtility.CheckNotNull("queryModel", queryModel);

            var joinResultSelector = Expression.Lambda(Expression.Constant(null), OuterKeySelector.Parameters[0],
                                                       InnerKeySelector.Parameters[0]);
            var joinParseInfo      = new MethodCallExpressionParseInfo(AssociatedIdentifier, Source, ParsedExpression);
            var joinExpressionNode = new JoinExpressionNode(joinParseInfo, InnerSequence, OuterKeySelector,
                                                            InnerKeySelector, joinResultSelector);

            var joinClause      = joinExpressionNode.CreateJoinClause(clauseGenerationContext);
            var groupJoinClause = new GroupJoinClause(ResultSelector.Parameters[1].Name,
                                                      ResultSelector.Parameters[1].Type, joinClause);

            clauseGenerationContext.AddContextInfo(this, groupJoinClause);
            queryModel.BodyClauses.Add(groupJoinClause);

            var selectClause = queryModel.SelectClause;

            selectClause.Selector = GetResolvedResultSelector(clauseGenerationContext);
        }