I'm seeking for a way to negate an expression used to filter IQueryable sequences.
So, I've got something like:
Expression<Func<T, bool>> expression = (x => true);
Now I wish to create the expression which would result in yielding (x => false) - so I basically want to negate the expression.
The working method I've found myself works like this:
var negatedExpression =
Expression.Lambda<Func<T, bool>> (Expression.Not(expression.Body),
expression.Parameters[0])));
But I'm almost sure there is a better way - could you help me? (something like Not(expression), probably).
An easy extension method:
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> one)
{
var candidateExpr = one.Parameters[0];
var body = Expression.Not(one.Body);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
Usage:
Expression<Func<int, bool>> condition = x => x > 5;
var source = Enumerable.Range(1, 10);
var result1 = source.Where(condition.Compile()); //6,7,8,9,10
var result2 = source.Where(condition.Not().Compile()); //1,2,3,4,5
Posting for future reference.
Danny Chen's answer can be made more generic:
public static Expression<TFunc> Not<TFunc>(this Expression<TFunc> baseExpr)
{
var param = baseExpr.Parameters;
var body = Expression.Not(baseExpr.Body);
var newExpr = Expression.Lambda<TFunc>(body, param);
return newExpr;
}
This version can receive an Expression with any number of input parameters. It only adds a little useability, however, since the Expression would most likely be passed to a function like IEnumerable.Where anyway.
What about this?
Expression<Func<bool>> expr = () => true;
Expression<Func<bool>> negated = () => !expr.Compile()();
Related
A C# lambda expression (of type System.Linq.Expressions.Expression<TDelegate>) in code:
Expression<Func<Something, bool>> predicate = s => s.SomeProperty == 12;
To create a similar instance of System.Linq.Expressions.Expression:
var parameter = Expression.Parameter(typeof(Something), "s");
var property = Expression.Property(parameter, typeof(Something).GetProperty("SomeProperty"));
var constant = Expression.Constant(12);
var expression = Expression.Equal(property, constant);
Is there a way to declare expression given only the predicate? So without building the expression tree step by step in code, but having the compiler infer it from a lambda expression.
var expression = Expression.FromLambda<Something>(s => s.SomeProperty == 12);
Sure, just grab the body of the lambda expression, like so:
Expression FromLambda(Expression<Func<Something, bool>> lambda)
{
return lambda.Body;
}
Then you can use it like so:
var expression = FromLambda(s => s.SomeProperty == 12);
Just return the expression
Expression<Func<T, bool>> FromLambda<T>(Expression<Func<T, bool>> lambda) {
return lambda;
}
And use as desired
var expression = FromLambda<Something>(s => s.SomeProperty == 12);
This however is not very flexible and targets just this scenario. You would need to create methods for any other delegate you want to use.
i try to query (linq to entities EF Core) a navigation properties collection, so i use any() like this :
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(p => p.myprop == myvar );
It's work perfectly but now i want to construct the predicate and not defined it directly in the query.
so i do :
Func<T, bool> mypredicate = (p => p.myprop == myvar);
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(mypredicate);
(I have replace T by my entity name)
but this generate an error : Object of type 'System.Linq.Expressions.TypedParameterExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
How can i construct my predicate to use it on Any() collection ?
Thank's
This line for example:
var query = context.MyTable.Where(x => x.mycollectionproperties.Any(p => p.myprop == 1));
When compiled will be compiled to something like this:
var xParameter = Expression.Parameter(typeof(Entity1), "x");
var pParameter = Expression.Parameter(typeof(Entity2), "p");
var anyMethod =
typeof(Enumerable)
.GetMethods()
.Single(x => x.Name == "Any" && x.GetParameters().Length == 2)
.MakeGenericMethod(typeof(Entity2));
var anyCondition = Expression.Lambda<Func<Entity2, bool>>(
Expression.Equal(
Expression.Property(
pParameter,
typeof(Entity2).GetProperty("myprop").GetMethod),
Expression.Constant(1, typeof(int))),
pParameter);
var query = context.MyTable.Where(
Expression.Lambda<Func<Entity1, bool>>(
Expression.Call(
null,
anyMethod,
new Expression[] {
Expression.Property(
xParameter,
typeof(Entity1).GetProperty("mycollectionproperties").GetMethod),
anyCondition
}),
xParameter));
This is called an expression tree. See this reference for more details:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/
Although the Any method takes a Func, when constructing the expression tree, notice that an expression (Expression<Func<Entity2, bool>>) is given to the Any method.
There doesn't seem to be a way from C# to give the Any method an expression instead of a Func even if the whole thing is an expression tree (I mean in a parameterized way like you want to achieve).
The most obvious way to achieve what you want is to use the code from this post and replace the anyCondition variable with whatever expression you want to use for the condition inside Any.
Another way is to construct part of the expression tree "normally" and pass null to the Any method and then use an expression visitor to replace the null with your expression. Here is how such visitor would look like:
public class AnyMethodArgumentReplacingVisitor : ExpressionVisitor
{
private readonly Expression expression;
public AnyMethodArgumentReplacingVisitor(Expression expression)
{
this.expression = expression;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == "Any")
{
return Expression.Call(node.Object, node.Method, node.Arguments[0], expression);
}
return base.VisitMethodCall(node);
}
}
Here is how you would use it:
Expression<Func<Entity2, bool>> predicate =
a => a.myprop == 2;
Expression<Func<Entity1, bool>> expression =
b => b.mycollectionproperties.Any(null);
var expression2 =
(Expression<Func<Entity1, bool>>)
new AnyMethodArgumentReplacingVisitor(predicate).Visit(expression);
Please note that such visitor would replace the call to any Any method. It also assumes that only the overload of Any that takes a predicate is used. There is another overload of Any that does not take a predicate. If you need to use that, you need to adjust the code.
It looks to me your problem is in your definition of
Func<T, bool> mypredicate = (p => p.myprop == myvar);
You should not use T, you should use the type of mycollectionproperties
Assuming the property mycollectionproperties is defined as something like this
....
public IQueryable<YourType> mycollectionproperties { get; set; }
....
Then you should declare mypredicate as
Func<YourType, bool> mypredicate = (p => p.myprop == myvar);
You can see a working sample on .NetFiddle
I have a list of Linq expressions like:
List<Expression<Func<Customer, bool>>>
I need to add a whole bunch of predicates from a search page, like:
x.Name.Contains(searchString)
x.Description.Contains(searchString)
...
I want to create a method so I don't end up with a mass of duplicated code. Something with a signature like:
void AddCustomerPredicate(List<Expression<Func<Customer, bool>>> predicates, Expression<Func<Customer, string>> prop, string searchString);
Which I would use like:
var predicates = new List<Expression<Func<Customer, bool>>>();
AddCustomerPredicate(predicates, x => x.Name, this.Name);
AddCustomerPredicate(predicates, x => x.Description, this.Description);
...
I've simplified the problem a bit, but that is the gist of it. I haven't done much work with expression trees and the like, so I'm not sure how to implement this method?
**EDIT**
I might have over simplified the problem too much. I know how to add to the list like predicates.Add(x => x.Name.Contains(this.searchString)), but I have various things I want to do on each search parameter before adding it to the list (e.g. check for null or empty). I therefore want to call a method on each search parameter as above, so all of that stuff can be contained in a single method.
What you really need is to have a method for translated Expression<Func<T, string>> to Expression<Func<T, bool>> :
public static Expression<Func<T, bool>> GetContainsExpression<T>(Expression<Func<T, string>> prop, string searchString)
{
var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(searchString, typeof(string));
var containsMethodExp = Expression.Call(prop.Body, method, someValue);
return Expression.Lambda<Func<T, bool>>(containsMethodExp, prop.Parameters[0]);
}
This is inspired by this other answer : How do I create an expression tree to represent 'String.Contains(“term”)' in C#?
var predicates = new List<Expression<Func<Customer, bool>>>();
predicates.Add(GetContainsExpression((Customer x) => x.Name, this.Name));
predicates.Add(GetContainsExpression((Customer x) => x.Description, this.Description));
I believe this will do what you want, and will also handle null property values (so calling Contains() does not throw):
private static void AddCustomerPredicate(
List<Expression<Func<Customer, bool>>> predicates,
Expression<Func<Customer, string>> accessor,
string searchString)
{
var x = accessor.Parameters[0];
var temp = Expression.Variable(typeof(string), "temp");
var predicate = Expression.Lambda<Func<Customer, bool>>(
Expression.Block(
new[] { temp },
Expression.Assign(
temp,
accessor.Body),
Expression.AndAlso(
Expression.IsFalse(
Expression.ReferenceEqual(
temp,
Expression.Default(typeof(string)))),
Expression.Call(
temp,
"Contains",
Type.EmptyTypes,
Expression.Constant(searchString)))),
x);
predicates.Add(predicate);
}
Suppose I have something like
Expression<Func<SomeType, DateTime>> left = x => x.SomeDateProperty;
Expression<Func<SomeType, DateTime>> right = x => dateTimeConstant;
var binaryExpression = Expression.GreaterThan(left, right);
Expression<Func<SomeType, bool>> predicate =
x => x.SomeDateProperty> dateTimeConstant;
1) How can I replace the right hand of the assignment of the last line with something that uses the binaryExpression instead? var predicate = x => binaryExpression; doesn't work.
2) The right is always a constant, not necessarily DateTime.Now. Could it be of some simpler Expression type? For instance, it doesn't depend on SomeType, it is just a constant.
3) If I have the GreaterThan as a string, is there a way to get from this string to the method with the same name in Expression? In general, if the name of the comparison method is given as a string, how can I go from the string to actually calling the method with the same name on the Expression class?
It has to work with LINQ to Entities, if it matters.
1 and 2: You need to build the expression tree manually to do this, the compiler cannot help because it only constructs ready-made expressions that represent functions in their entirety. That's not useful when you want to build functions piece by piece.
Here's one straightforward way to build the expression you want:
var argument = Expression.Parameter(typeof(SomeType));
var left = Expression.Property(argument, "SomeDateProperty");
var right = Expression.Constant(DateTime.Now);
var predicate = Expression.Lambda<Func<SomeType, bool>>(
Expression.GreaterThan(left, right),
new[] { argument }
);
You can take this for a test drive with
var param = new SomeType {
SomeDateProperty = DateTime.Now.Add(TimeSpan.FromHours(-1))
};
Console.WriteLine(predicate.Compile()(param)); // "False"
3: Since in all likelihood the number of possible choices for your binary predicate will be quite small, you could do this with a dictionary:
var wordToExpression =
new Dictionary<string, Func<Expression, Expression, BinaryExpression>>
{
{ "GreaterThan", Expression.GreaterThan },
// etc
};
Then, instead of hardcoding Expression.GreaterThan in the first snippet you would do something like wordToExpression["GreaterThan"](left, right).
Of course this can also be done the standard way with reflection.
When you use GreaterThan, you need to specify the expression bodies, not the lambda itself. Unfortunately, there is a complication: the x in the two expressions is not the same.
In this particular case, you could just about get away with this, because the second expression does not use x
So; your "1" and "2" should be answered by:
var binaryExpression = Expression.GreaterThan(left.Body, right.Body);
var lambda = Expression.Lambda<Func<SomeType, bool>>(binaryExpression,
left.Parameters);
However, to handle this in the general case, you must rewrite on of the expressions, to fix-up the parameters:
var binaryExpression = Expression.GreaterThan(left.Body,
new SwapVisitor(right.Parameters[0], left.Parameters[0]).Visit(right.Body));
var lambda = Expression.Lambda<Func<SomeType, bool>>(binaryExpression,
left.Parameters);
with:
public class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
For your "3"; there is nothing inbuilt for that; you could use reflection, though:
string method = "GreaterThan";
var op = typeof(Expression).GetMethod(method,
BindingFlags.Public | BindingFlags.Static,
null, new[] { typeof(Expression), typeof(Expression) }, null);
var rightBody = new SwapVisitor(right.Parameters[0],
left.Parameters[0]).Visit(right.Body);
var exp = (Expression)op.Invoke(null, new object[] { left.Body, rightBody });
var lambda = Expression.Lambda<Func<SomeType, bool>>(exp, left.Parameters);
How would I go about using an Expression Tree to dynamically create a predicate that looks something like...
(p.Length== 5) && (p.SomeOtherProperty == "hello")
So that I can stick the predicate into a lambda expression like so...
q.Where(myDynamicExpression)...
I just need to be pointed in the right direction.
Update: Sorry folks, I left out the fact that I want the predicate to have multiple conditions as above. Sorry for the confusion.
Original
Like so:
var param = Expression.Parameter(typeof(string), "p");
var len = Expression.PropertyOrField(param, "Length");
var body = Expression.Equal(
len, Expression.Constant(5));
var lambda = Expression.Lambda<Func<string, bool>>(
body, param);
Updated
re (p.Length== 5) && (p.SomeOtherProperty == "hello"):
var param = Expression.Parameter(typeof(SomeType), "p");
var body = Expression.AndAlso(
Expression.Equal(
Expression.PropertyOrField(param, "Length"),
Expression.Constant(5)
),
Expression.Equal(
Expression.PropertyOrField(param, "SomeOtherProperty"),
Expression.Constant("hello")
));
var lambda = Expression.Lambda<Func<SomeType, bool>>(body, param);
Use the predicate builder.
http://www.albahari.com/nutshell/predicatebuilder.aspx
Its pretty easy!
To combine several predicates with the && operator, you join them together two at a time.
So if you have a list of Expression objects called predicates, do this:
Expression combined = predicates.Aggregate((l, r) => Expression.AndAlso(l, r));
To associate Lambda expression each other:
An other way is to use the following code. It s more flexible than the Schotime answer in my advice and work perfectly. No external Nuggets needed
Framework 4.0
// Usage first.Compose(second, Expression.And)
public static Expression<T> Compose<T>(this Expression<T> First, Expression<T> Second, Func<Expression, Expression, Expression> Merge)
{
// build parameter map (from parameters of second to parameters of first)
Dictionary<ParameterExpression,ParameterExpression> map = First.Parameters.Select((f, i) => new { f, s = Second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with parameters from the first
Expression secondBody = ParameterRebinder.ReplaceParameters(map, Second.Body);
// apply composition of lambda expression bodies to parameters from the first expression
return Expression.Lambda<T>(Merge(First.Body, secondBody), First.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> Second)
{
return First.Compose(Second, Expression.And);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> second)
{
return First.Compose(second, Expression.Or);
}
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
I have a open-source project called Exprelsior that provides very simple ways to create dynamic predicates:
Based on your example:
var exp1 = ExpressionBuilder.CreateBinary<YourClass>("MyProperty.Length", 5, ExpressionOperator.Equals);
var exp2 = ExpressionBuilder.CreateBinary<YourClass>("SomeOtherProperty", "hello", ExpressionOperator.Equals);
var fullExp = exp1.And(exp2);
// Use it normally...
q.Where(fullExp)
It even supports full text predicate generation, so you can receive any dynamic query from an HTTP GET method, for example:
var exp1 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('MyProperty.Length', '5')");
var exp2 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('SomeOtherProperty', 'hello')");
var fullExp = exp1.And(exp2);
// Use it normally...
q.Where(fullExp)
It supports a lot more data types and operators.
Link: https://github.com/alexmurari/Exprelsior