Skip to content

Commit

Permalink
Enumerable parser now supports all expression types.
Browse files Browse the repository at this point in the history
  • Loading branch information
franzalex committed Jan 30, 2016
1 parent 3035bd3 commit 8a6e093
Showing 1 changed file with 20 additions and 9 deletions.
29 changes: 20 additions & 9 deletions LiteDB/Query/Linq/QueryVisitor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
using ParameterDictionary = System.Collections.Generic.Dictionary<System.Linq.Expressions.ParameterExpression,
LiteDB.BsonValue>;

namespace LiteDB
{
Expand All @@ -11,11 +13,13 @@ internal class QueryVisitor<T>
{
private BsonMapper _mapper;
private Type _type;
private ParameterDictionary parameters;

public QueryVisitor(BsonMapper mapper)
{
_mapper = mapper;
_type = typeof(T);
parameters = new ParameterDictionary();
}

public Query Visit(Expression predicate)
Expand Down Expand Up @@ -141,6 +145,17 @@ private BsonValue VisitValue(Expression expr)

return _mapper.Serialize(value);
}
else if (expr is MemberExpression && parameters.Count > 0)
{
var mExpr = (MemberExpression)expr;
return _mapper.Serialize(this.VisitValue(mExpr.Expression).AsDocument[mExpr.Member.Name]);
}
else if (expr is ParameterExpression)
{
BsonValue result;
if (parameters.TryGetValue((ParameterExpression)expr, out result))
return result;
}

// execute expression
var objectMember = Expression.Convert(expr, typeof(object));
Expand Down Expand Up @@ -239,22 +254,18 @@ private Query ParseEnumerableExpression(MethodCallExpression expr)
if (expr.Method.DeclaringType.FullName != "System.Linq.Enumerable")
throw new NotImplementedException("Cannot parse methods outside the System.Linq.Enumerable class.");

// we currently support method calls only.
// TODO: Expand to support the full range of expressions
var methodBody = ((LambdaExpression)expr.Arguments[1]).Body as MethodCallExpression;
if (methodBody == null)
throw new NotImplementedException("Unsupported expression in the body of the lambda expression.");

var lambda = (LambdaExpression)expr.Arguments[1];
var values = this.VisitValue(expr.Arguments[0]).AsArray;
var queries = new Query[values.Count];

for (var i = 0; i < queries.Length; i++)
{
var newValue = Expression.Constant(values[i].RawValue);
var newMethod = methodBody.Update(methodBody.Object, new[] { newValue });
queries[i] = this.VisitExpression(newMethod);
parameters[lambda.Parameters[0]] = values[i];
queries[i] = this.VisitExpression(lambda.Body);
}

parameters.Remove(lambda.Parameters[0]);

if (expr.Method.Name == "Any")
return CreateOrQuery(ref queries);
else if (expr.Method.Name == "All")
Expand Down

0 comments on commit 8a6e093

Please sign in to comment.