/// <remarks>
        /// This build method caters to expressions like: <code>item => item.As&lt;Foo&gt;().Bar</code>
        /// </remarks>
        static string BuildText(MemberExpression expression, bool camelCaseProperties)
        {
            var innerExpression = expression.Expression as MethodCallExpression;

            if (innerExpression == null ||
                innerExpression.Method.DeclaringType != typeof(ICypherResultItem) ||
                innerExpression.Method.Name != "As")
            {
                throw new ArgumentException("Member expressions are only supported off ICypherResultItem.As<TData>(). For example: Return(foo => foo.As<Bar>().Baz).", "expression");
            }

            var baseStatement = BuildStatement(innerExpression, false);
            var statement     = string.Format("{0}.{1}", baseStatement, CypherFluentQuery.ApplyCamelCase(camelCaseProperties, expression.Member.GetNameUsingJsonProperty()));

            return(statement);
        }
        static string BuildStatement(
            MemberExpression memberExpression,
            MemberInfo targetMember,
            CypherCapabilities capabilities,
            bool camelCaseProperties)
        {
            MethodCallExpression methodCallExpression;
            MemberInfo           memberInfo;

            if (memberExpression.NodeType == ExpressionType.MemberAccess && memberExpression.Expression.NodeType == ExpressionType.Call)
            {
                methodCallExpression = (MethodCallExpression)memberExpression.Expression;
                memberInfo           = memberExpression.Member;
            }
            else if (memberExpression.NodeType == ExpressionType.MemberAccess && memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
            {
                var nextedExpression = ((MemberExpression)memberExpression.Expression);
                methodCallExpression = (MethodCallExpression)nextedExpression.Expression;
                memberInfo           = nextedExpression.Member;
            }
            else
            {
                throw new NotSupportedException(string.Format("The expression {0} is not supported", memberExpression));
            }
            var targetObject = (ParameterExpression)methodCallExpression.Object;

            if (targetObject == null)
            {
                throw new InvalidOperationException(
                          "Somehow targetObject ended up as null. We weren't expecting this to happen. Please raise an issue at https://github.com/Readify/Neo4jClient including your query code.");
            }

            var optionalIndicator = "";

            if (capabilities.SupportsPropertySuffixesForControllingNullComparisons)
            {
                var isTargetMemberNullable = IsMemberNullable(targetMember);
                var isNullable             = isTargetMemberNullable || IsMemberNullable(memberInfo);
                if (isNullable)
                {
                    optionalIndicator = "?";
                }
            }

            return(string.Format("{0}.{1}{2} AS {3}", targetObject.Name, CypherFluentQuery.ApplyCamelCase(camelCaseProperties, memberInfo.Name), optionalIndicator, targetMember.Name));
        }
        void VisitParameterMember(MemberExpression node)
        {
            var identityExpression = node.Expression as ParameterExpression;

            if (identityExpression == null &&
                node.Expression.NodeType == ExpressionType.Convert)
            {
                identityExpression = ((UnaryExpression)node.Expression).Operand as ParameterExpression;
            }
            if (identityExpression == null)
            {
                throw new InvalidOperationException("Failed to extract identity name from expression " + node);
            }
            var identity = identityExpression.Name;

            var nullIdentifier = string.Empty;

            var propertyParent = node.Member.ReflectedType;
            var propertyType   = propertyParent.GetProperty(node.Member.Name).PropertyType;

            if (capabilities.SupportsPropertySuffixesForControllingNullComparisons)
            {
                var isNullable = propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>);
                if (isNullable || propertyType == typeof(string))
                {
                    nullIdentifier = "?";
                }
            }

            JsonPropertyAttribute[] jsonProperties = (JsonPropertyAttribute[])node.Member.GetCustomAttributes(typeof(JsonPropertyAttribute), true);
            JsonPropertyAttribute   jsonProperty   = jsonProperties.SingleOrDefault();
            string memberName = null;

            if (jsonProperty != null)
            {
                memberName = jsonProperty.PropertyName;
            }
            if (string.IsNullOrWhiteSpace(memberName))
            {
                memberName = CypherFluentQuery.ApplyCamelCase(camelCaseProperties, node.Member.Name);
            }

            lastWrittenMemberName = string.Format("{0}.{1}{2}", identity, memberName, nullIdentifier);
            TextOutput.Append(lastWrittenMemberName);
        }
        /// <remarks>
        /// This build method caters to expressions like: <code>item => item.As&lt;Foo&gt;().Bar</code>
        /// </remarks>
        static string BuildText(
            MemberExpression expression,
            CypherCapabilities capabilities,
            IEnumerable <JsonConverter> jsonConvertersThatTheDeserializerWillUse,
            bool camelCaseProperties)
        {
            var innerExpression = expression.Expression as MethodCallExpression;

            if (innerExpression == null ||
                innerExpression.Method.DeclaringType != typeof(ICypherResultItem) ||
                innerExpression.Method.Name != "As")
            {
                throw new ArgumentException("Member expressions are only supported off ICypherResultItem.As<TData>(). For example: Return(foo => foo.As<Bar>().Baz).", "expression");
            }

            var baseStatement = BuildStatement(innerExpression, false, capabilities, jsonConvertersThatTheDeserializerWillUse);
            var statement     = string.Format("{0}.{1}", baseStatement, CypherFluentQuery.ApplyCamelCase(camelCaseProperties, expression.Member.Name));

            return(statement);
        }