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]);

            JoinExpressionNode = new JoinExpressionNode(parseInfo, innerSequence, outerKeySelector, innerKeySelector, joinResultSelector);

            ResultSelector        = resultSelector;
            _cachedResultSelector = new ResolvedExpressionCache <Expression> (this);
        }
    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]);
      JoinExpressionNode = new JoinExpressionNode (parseInfo, innerSequence, outerKeySelector, innerKeySelector, joinResultSelector);
      
      ResultSelector = resultSelector;
      _cachedResultSelector = new ResolvedExpressionCache<Expression> (this);
    }
        protected override QueryModel ApplyNodeSpecificSemantics(QueryModel queryModel, ClauseGenerationContext clauseGenerationContext)
        {
            ArgumentUtility.CheckNotNull("queryModel", queryModel);

            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);

            return(queryModel);
        }