Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linq Expression Feature #27

Merged
merged 4 commits into from
Oct 3, 2016

Conversation

alexis-
Copy link
Contributor

@alexis- alexis- commented Sep 14, 2016

  • Added Expression<Func<T, bool>> ToLinqExpression() Method which converts a FilterScheme instance to a LINQ Expression.
  • Added a simple test to compare ToLinqExpression with ComputeResult results. More tests should be added to make sure all operators are operational.
  • FilterScheme.Apply uses ToLinqExpression.
  • TODO: Add Regex and Enum (StringExpression) handling in ToLinqExpression

…hod which converts a FilterScheme instance to a LINQ Expression.

* Added a simple test to compare ToLinqExpression with ComputeResult results. More tests should be added to make sure all operators are operational.
* **FilterScheme.Apply** uses **ToLinqExpression**.
* TODO: Add Regex and Enum (**StringExpression**) handling in **ToLinqExpression**
@alexis-
Copy link
Contributor Author

alexis- commented Sep 14, 2016

I went with reverting develop to upstream commit, creating new branches, and adding changes step-by-step.
I kept a local-develop branch of my previous version, and a hard backup.

Regarding the PR, does this work for you ?
Other PR will follow soon.

Regarding the UI, I appreciate your concern. It probably won't come as a surprise to you, but it was built for use in my own application. No work is wasted, apart from the reverting-branching overhead.

@GeertvanHorrik
Copy link
Member

@michu could you please give a quick review here?

@GeertvanHorrik
Copy link
Member

@mkhomutov , please also do a review of this.

@mkhomutov
Copy link
Member

OK will do it tomorrow

Copy link
Member

@mkhomutov mkhomutov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code looks really good. I've added few comments which would improve.

case Condition.NotIsEmpty:
return Expression.NotEqual(propertyExpr, Expression.Constant(string.Empty));
case Condition.IsNull:
return Expression.Equal(propertyExpr, Expression.Constant(null));
Copy link
Member

@mkhomutov mkhomutov Sep 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please, replace to Expression.ReferenceEqual()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is only for null checking

case Condition.IsNull:
return Expression.Equal(propertyExpr, Expression.Constant(null));
case Condition.NotIsNull:
return Expression.NotEqual(propertyExpr, Expression.Constant(null));
Copy link
Member

@mkhomutov mkhomutov Sep 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please, replace to Expression.ReferenceNotEqual()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only for null checking

return Expression.NotEqual(propertyExpr, valueExpr);

case Condition.Contains:
operatorExpr = Expression.Call(propertyExpr, typeof(string).GetMethod("Contains", new[] { typeof(string) }), valueExpr);
Copy link
Member

@mkhomutov mkhomutov Sep 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of GetMethod() better to use GetMethodEx() extension method everywhere.
it uses cache under the hood, so works a bit faster

break;

case Condition.DoesNotStartWith:
operatorExpr = Expression.IsFalse(Expression.Call(propertyExpr, typeof(string).GetMethod("StartsWith", new[] { typeof(string), typeof(StringComparison) }), valueExpr, Expression.Constant(StringComparison.CurrentCultureIgnoreCase)));
Copy link
Member

@mkhomutov mkhomutov Sep 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use constants instead of such strings as "StartsWith" or "Contains"

filteredCollection.Add(item);
}

#if false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why is it for

/// </summary>
/// <param name="parameterExpr">LINQ ParameterExpression.</param>
/// <returns>LINQ Expression.</returns>
public abstract Expression ToLinqExpression(Expression parameterExpr);
Copy link
Member

@mkhomutov mkhomutov Sep 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably combine all ToLinqExpresison() methods and move it into the Extensions class or some "LinqExpressionConverter"
not sure, but it looks and sounds like extension and looks like it is not really needed to put all this logic in separate classes

/// </summary>
/// <param name="propertyExpr">LINQ <see cref="MemberExpression"/>.</param>
/// <returns>LINQ Expression.</returns>
public override Expression ToLinqExpression(Expression propertyExpr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use Argument.IsNotNull(() => propertyExpr)
everywhere for null checking the arguments

@alexis-
Copy link
Contributor Author

alexis- commented Sep 17, 2016

Excellent, I appreciate the explanation bits you joined in your code review.
I will look into this matter soon.

@alexis-
Copy link
Contributor Author

alexis- commented Sep 26, 2016

All done -- at the exception of the extension class.
I agree it would be best to move the logic in their own file.
Perhaps I will do it at some point if required by future changes, but I have to dedicate my time to other tasks for the moment.

Let me know if this works for you.
Cheers,
Alex.

@@ -134,9 +141,9 @@ public override Expression ToLinqExpression(Expression propertyExpr)
case Condition.NotIsEmpty:
return Expression.NotEqual(propertyExpr, Expression.Constant(string.Empty));
case Condition.IsNull:
return Expression.Equal(propertyExpr, Expression.Constant(null));
return Expression.ReferenceEqual(propertyExpr, Expression.Constant(null));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this code? Not sure if calling Expression.Constant(null) returns the same actual reference every time. This is just an observation, I am not entirely sure about this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a test to make sure. This is the way Microsoft suggest using null constants (see https://msdn.microsoft.com/en-us/library/bb349084(v=vs.110).aspx )

@@ -198,16 +205,16 @@ public override Expression ToLinqExpression(Expression propertyExpr)
.IsMatch(entityValue);
*/
case Condition.GreaterThan:
return Expression.GreaterThan(Expression.Call(Expression.Constant(null, typeof(string)), typeof(string).GetMethod("Compare", comparisonMethodParams), propertyExpr, valueExpr, Expression.Constant(StringComparison.CurrentCultureIgnoreCase)), Expression.Constant(0, typeof(int)));
return Expression.GreaterThan(Expression.Call(Expression.Constant(null, typeof(string)), typeof(string).GetMethodEx("Compare", comparisonMethodParams), propertyExpr, valueExpr, Expression.Constant(StringComparison.CurrentCultureIgnoreCase)), Expression.Constant(0, typeof(int)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also move these "Compare" to CompareMethodName

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@alexis-
Copy link
Contributor Author

alexis- commented Sep 26, 2016

A quick reminder, RegEx and Enum aren't yet supported in this PR.

@GeertvanHorrik
Copy link
Member

@mkhomutov if you agree with this PR, please merge & release.

@lock
Copy link

lock bot commented Aug 27, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Aug 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants