Skip to content

Commit

Permalink
Merge pull request #209 from PhyberApex/feature/nestedfilter
Browse files Browse the repository at this point in the history
Added nested filter
  • Loading branch information
joukevandermaas authored Oct 26, 2018
2 parents e50d8ca + 724e90b commit 9edcbb6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 8 deletions.
43 changes: 36 additions & 7 deletions Saule/Queries/Lambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ public static Expression SelectPropertyValue(Type type, string property, List<st
}

var param = Expression.Parameter(type, "i");
var propertyExpression = Expression.Property(param, property);
Expression propertyExpression = param;
foreach (var member in property.Split('.'))
{
propertyExpression = Expression.PropertyOrField(propertyExpression, member);
}

var expression = queryFilter.GetQueryFilterExpression(type.GetProperty(property));
var expression = queryFilter.GetQueryFilterExpression(GetPropertyInfo(type, property));

return typeof(Lambda)
.GetMethod(nameof(Convert), BindingFlags.Static | BindingFlags.NonPublic)
Expand Down Expand Up @@ -74,17 +78,42 @@ private static Expression<Func<TClass, bool>> Convert<TProperty, TClass>(

private static Type GetPropertyType(Type type, string property)
{
var returnType = type.GetProperty(property)?.PropertyType;
if (returnType == null)
List<string> properties = property.Split('.').ToList();
var returnType = type;
foreach (string prop in properties)
{
throw new ArgumentException(
$"Property {property} does not exist.",
nameof(property));
returnType = returnType.GetProperty(prop)?.PropertyType;
if (returnType == null)
{
throw new ArgumentException(
$"Property {property} does not exist.",
nameof(property));
}
}

return returnType;
}

private static PropertyInfo GetPropertyInfo(Type type, string property)
{
List<string> properties = property.Split('.').ToList();
var tmpType = type;
PropertyInfo propertyInfo = tmpType.GetProperty(property);
foreach (string prop in properties)
{
propertyInfo = tmpType.GetProperty(prop);
tmpType = tmpType.GetProperty(prop)?.PropertyType;
if (tmpType == null)
{
throw new ArgumentException(
$"Property {property} does not exist.",
nameof(property));
}
}

return propertyInfo;
}

private static MethodInfo CreateExpressionFactory(Type funcType)
{
var expressionFactory = typeof(Expression).GetMethods()
Expand Down
6 changes: 6 additions & 0 deletions Tests/Helpers/Get.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ internal static class Get
"North Street", "Heritage Drive", "Cooper Street", "Route 44",
};

private static readonly string[] CompanyNames =
{
"Awesome Inc.", "Seen Better Days Co", "Stock Inc.", "Bookstore", "Office Supplies",
};

public static IEnumerable<Person> People()
{
var i = 0;
Expand Down Expand Up @@ -95,6 +100,7 @@ public static Company Company(string id = "456")
{
return new Company(prefill: true, id: id)
{
Name = CompanyNames[random.Next(CompanyNames.Length)],
Location = (LocationType)random.Next(Enum.GetNames(typeof(LocationType)).Length)
};
}
Expand Down
14 changes: 13 additions & 1 deletion Tests/Queries/FilterInterpreterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,25 @@ public void WorksOnStrings()
Assert.Equal(expected, result);
}

[Fact(DisplayName = "Applies nested filtering on strings")]
public void WorksOnNestedStrings()
{
var people = Get.People(100).ToList().AsQueryable();
var expected = people.Where(c => c.Job.Name == "Bookstore").ToList();
var query = GetQuery(new[] { "Job.Name" }, new[] { "Bookstore" });
var result = Query.ApplyFiltering(people, new FilterContext(query), new PersonResource())
as IQueryable<Person>;

Assert.Equal(expected, result);
}

[Fact(DisplayName = "Applies filtering on strings with spaces")]
public void WorksOnStringsWithSpaces()
{
var companies = Get.Companies(100).ToList().AsQueryable();
var expected = companies.Where(c => c.Name == "Awesome Inc.").ToList();

var query = GetQuery(new[] { "Name" }, new[] { "Aweseom Inc." });
var query = GetQuery(new[] { "Name" }, new[] { "Awesome Inc." });

var result = Query.ApplyFiltering(companies, new FilterContext(query), new CompanyResource())
as IQueryable<Company>;
Expand Down

0 comments on commit 9edcbb6

Please sign in to comment.