Skip to content

Commit

Permalink
support for method calls on string, this would help database drivers …
Browse files Browse the repository at this point in the history
…like mongo or even other database that have a string collation that is case sensitive.
  • Loading branch information
David Lebee committed Apr 27, 2021
1 parent e7a3b06 commit 15aeb2a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
64 changes: 64 additions & 0 deletions PoweredSoft.DynamicLinq.Test/SimpleQueriesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,70 @@ public void Equal()
Assert.IsTrue(newQuery.Any(), "Must have at least one author that matches");
}

[TestMethod]
public void EqualLowerCase()
{
// subject.
var authors = new List<Author>()
{
new Author { Id = long.MaxValue, FirstName = "David", LastName = "Lebee" }
};

// the query.
var query = authors.AsQueryable();

// simple where.
var newQuery = query.Where("FirstName.ToLower()", ConditionOperators.Equal, "david");

// must match.
Assert.IsTrue(newQuery.Any(), "Must have at least one author that matches");
}

[TestMethod]
public void EqualLowerCaseNullCheck()
{
// subject.
var authors = new List<Author>()
{
new Author { Id = long.MaxValue, FirstName = null, LastName = "Lebee" },
new Author { Id = long.MaxValue, FirstName = "David", LastName = "Lebee" },
};

// the query.
var query = authors.AsQueryable();

// simple where.
var newQuery = query.Where(wb =>
{
wb.Equal("FirstName.ToLower()", "david").NullChecking(true);
});

// must match.
Assert.IsTrue(newQuery.Any(), "Must have at least one author that matches");
}

[TestMethod]
public void DoubleMethodCheck()
{
// subject.
var authors = new List<Author>()
{
new Author { Id = long.MaxValue, FirstName = "David ", LastName = "Lebee" },
};

// the query.
var query = authors.AsQueryable();

// simple where.
var newQuery = query.Where(wb =>
{
wb.Equal("FirstName.Trim().ToLower()", "david").NullChecking(true);
});

// must match.
Assert.IsTrue(newQuery.Any(), "Must have at least one author that matches");
}

[TestMethod]
public void Contains()
{
Expand Down
29 changes: 26 additions & 3 deletions PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using PoweredSoft.DynamicLinq.Resolver;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
Expand Down Expand Up @@ -471,8 +472,18 @@ internal static Expression InternalCreateConditionExpression(int recursionStep,
var partStr = parts.First();
var isLast = parts.Count == 1;

// the member expression.
var memberExpression = Expression.PropertyOrField(current, partStr);
Expression memberExpression;
if (current != null && current.Type == typeof(string) && partStr.Contains("()"))
{
var finalMethodName = partStr.Replace("()", string.Empty);
var callingMethod = GetStringCallingMethod(finalMethodName); //typeof(string).GetMethod(finalMethodName, new Type[0]);
memberExpression = Expression.Call(current, callingMethod);
}
else
{
// the member expression.
memberExpression = Expression.PropertyOrField(current, partStr);
}

// TODO : maybe support that last part is collection but what do we do?
// not supported yet.
Expand Down Expand Up @@ -535,7 +546,19 @@ internal static Expression InternalCreateConditionExpression(int recursionStep,
}
}

public static Expression InAndNotIn(ParameterExpression parameter, ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, MemberExpression memberExpression)
private static ConcurrentDictionary<string, MethodInfo> _stringMethodCache = new ConcurrentDictionary<string, MethodInfo>();
private static MethodInfo GetStringCallingMethod(string methodName)
{
if (methodName == null)
throw new ArgumentNullException(nameof(methodName));

return _stringMethodCache.GetOrAdd(methodName, mn =>
{
return typeof(string).GetMethod(mn, new Type[0]);
});
}

public static Expression InAndNotIn(ParameterExpression parameter, ConditionOperators condition, object value, QueryConvertStrategy convertStrategy, Expression memberExpression)
{
var enumerableValue = value as IEnumerable;
if (enumerableValue == null)
Expand Down

0 comments on commit 15aeb2a

Please sign in to comment.