private void VisitMethodCall(ParameterExpression[] parameters, MethodCallExpression expression, QueryContainer container)
        {
            var declaringType = expression.Method.DeclaringType;
            var enumerableType = (declaringType.GetInterfaces()
                                      .Where(x => x.IsGenericType)
                                      .Where(x => x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                                      .Select(x => x.GetGenericArguments()[0])
                                      .FirstOrDefault() != null);
            if (enumerableType && expression.Method.Name == "Contains")
            {
                var memberExpression = expression.Object as MemberExpression;
                if (memberExpression != null)
                {
                    var constantExpression = memberExpression.Expression as ConstantExpression;
                    var prop = memberExpression.Member;
                    var fieldName = prop.Name;
                    if (constantExpression != null)
                    {
                        var value = constantExpression.Value;
                        var fieldType = value.GetType();
                        var fieldInfo = fieldType.GetField(fieldName);
                        var field = fieldInfo.GetValue(value);
                        var bsonValue = BsonArray.Create(field);
                        var inverted = container.Query.Inverted;
                        container.Query = new InRepositoryQuery { Value = bsonValue, Inverted = inverted };
                    }
                }
                Visit(parameters, expression.Arguments[0], container);
            }
            else if ((declaringType == typeof(IEnumerable) || declaringType == typeof(Enumerable) && declaringType != typeof(string) && declaringType.IsPrimitive == false) && expression.Method.Name == "Contains")
            {

                var inverted = container.Query.Inverted;
                var memberExpression = expression.Arguments[0] as MemberExpression;

                if (memberExpression != null && memberExpression.Expression is ParameterExpression)
                {
                    container.Query.Operand = MongoOperand.Equals;
                }
                else
                {
                    container.Query = new InRepositoryQuery { Inverted = inverted };
                }
                Visit(parameters, expression.Arguments[0], container);
                Visit(parameters, expression.Arguments[1], container);
            }
            else if (expression.Method.Name == "get_Item" &&
                     expression.Object != null &&
                     expression.Object.Type.GetGenericTypeDefinition() == typeof(Dictionary<,>))
            {
                Visit(parameters, expression.Object, container);
                var dictionaryKey = GetValueFromExpression(expression.Arguments[0]) as string;
                container.Query.PropertyName += "." + dictionaryKey; //Append the dictionary key
            }
            else if(expression.Method.Name == "IsNullOrEmpty")
            {
                var orRepositoryQuery = new OrRepositoryQuery
                                            {
                                                LeftContainer = new QueryContainer(new RepositoryQuery())
                                                                    {
                                                                        Query =
                                                                            {
                                                                                Value = "",
                                                                                Operand = MongoOperand.Equals,
                                                                                Inverted = container.Query.Inverted
                                                                            }
                                                                    }
                                            };
                Visit(null, expression.Arguments[0], orRepositoryQuery.LeftContainer);
                orRepositoryQuery.RightContainer = new QueryContainer(new RepositoryQuery())
                                                       {
                                                           Query =
                                                               {
                                                                   Value = null,
                                                                   Operand = MongoOperand.Equals,
                                                                   Inverted = container.Query.Inverted
                                                               }
                                                       };

                Visit(null, expression.Arguments[0], orRepositoryQuery.RightContainer);
                container.Query = orRepositoryQuery;
            }
            else if(expression.Method.Name == "IsNotNullOrEmpty")
            {
                var orRepositoryQuery = new OrRepositoryQuery
                                            {
                                                LeftContainer = new QueryContainer(new RepositoryQuery())
                                                                    {
                                                                        Query =
                                                                            {
                                                                                Value = "",
                                                                                Operand = MongoOperand.NotEquals
                                                                            }
                                                                    }
                                            };
                Visit(null, expression.Arguments[0], orRepositoryQuery.LeftContainer);
                orRepositoryQuery.RightContainer = new QueryContainer(new RepositoryQuery())
                                                       {
                                                           Query =
                                                               {
                                                                   Value = null,
                                                                   Operand = MongoOperand.NotEquals
                                                               }
                                                       };

                Visit(null, expression.Arguments[0], orRepositoryQuery.RightContainer);
                container.Query = orRepositoryQuery;
            }
            else if (expression.Method.Name == "Parse")
            {
                var memberExpression = expression.Arguments[0] as MemberExpression;
                if (expression.Arguments[0] is ConstantExpression || (memberExpression != null && memberExpression.Expression is ConstantExpression))
                {
                    var value = GetValueFromExpression(expression);
                    container.Query.Value = BsonValue.Create(value);
                }
                else
                {
                    throw new NotSupportedException("Parse on non-Constant Expressions is not supported");
                }
            }
            else if (expression.Method.Name == "ToString")
            {
                var memberExpression = expression.Object as MemberExpression;
                if (expression.Object is ConstantExpression || (memberExpression != null && memberExpression.Expression is ConstantExpression))
                {
                    var value = GetValueFromExpression(expression);
                    container.Query.Value = BsonValue.Create(value);
                }
                else
                {
                    throw new NotSupportedException("ToString on non-Constant Expressions is not supported");
                }
            }
            else
            {
                throw new NotSupportedException(string.Format("Method {0} is not supported", expression.Method.Name));
            }
        }
        private void VisitBinary(ParameterExpression[] parameters, BinaryExpression binaryExpression, QueryContainer container)
        {
            QueryContainer queryLeft;
            QueryContainer queryRight;
            switch (binaryExpression.NodeType)
            {
                case ExpressionType.AndAlso:
                case ExpressionType.And:
                    var andQuery = new AndRepositoryQuery();
                    queryLeft = new QueryContainer(new RepositoryQuery());
                    queryRight = new QueryContainer(new RepositoryQuery());
                    andQuery.LeftContainer = queryLeft;
                    andQuery.RightContainer = queryRight;
                    container.Query = andQuery;
                    break;
                case ExpressionType.Or:
                case ExpressionType.OrElse:
                    var orQuery = new OrRepositoryQuery();
                    queryLeft = new QueryContainer(new RepositoryQuery());
                    queryRight = new QueryContainer(new RepositoryQuery());
                    orQuery.LeftContainer = queryLeft;
                    orQuery.RightContainer = queryRight;
                    container.Query = orQuery;
                    break;
                default:
                    container.Query.Operand = FindMongoOperand(binaryExpression.NodeType);
                    queryLeft = queryRight = container;
                    break;

            }
            Visit(parameters, binaryExpression.Left, queryLeft);
            Visit(parameters, binaryExpression.Right, queryRight);
        }