Given:
var paramA = Expression.Parameter(typeof(string), "a");
and:
Expression<Func<string, bool>> expr = b => b == "Something";
Is there anyway to replace b by paramA into the expression expr?
You can walk the expression tree of expr, and replace all occurrences of b with paramA using the approach described in this Q&A: "Combine two lambda expressions with inner expression".
However, if you simply need a lambda expression that uses paramA as its parameter, it is easier to make a lambda that wraps expr instead:
var res = (Expression<Func<string,bool>>)Expression.Lambda(
Expression.Invoke(expr, paramA)
, paramA
);
Related
I'm trying to use this example to dinamically pass table field names to queries and avoid repeating frequent query operations for each table field.
The code contained in the example and edited as I need is the following:
Expression<Func<T, bool>> GreatherThan<T>(string field, string value)
{
ParameterExpression B = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, bool>>(
Expression.GreaterThan(
Expression.PropertyOrField(B, field),
Expression.Constant(value)),
B);
}
It works fine with numeric fields, as it has under Expression every operation that I need for a numeric field (equal, not equal, greater/less than, etc...).
But it seems there is no operation for strings, as Contains or similar. (Except Equal and NotEqual, of course.)
How can I achieve something like the following? (which by now is syntactically wrong but it's for example purpose)
Expression<Func<T, bool>> Contains<T>(string field, string value)
{
ParameterExpression B = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, bool>>(
Expression.Contains(
Expression.PropertyOrField(B, field),
Expression.Constant(value)),
B);
}
You have to call the method on the string object:
var s = Expression.Parameter(typeof(string), "s");
var term = Expression.Parameter(typeof(string), "term");
var contains = Expression.Call(s, typeof(string).GetMethod("Contains"), term);
Func<string, string, bool> lambda = Expression.Lambda<Func<string,string,bool>>(contains, s, term).Compile();
Console.WriteLine(lambda("test", "e")); //True
I have this code which produce a delegate which multiply myNumber by 5
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numMultiply = Expression.Multiply(numParam,five);
Lets create the delegate :
Expression<Func<int, int>> lambda1 =
Expression.Lambda<Func<int, int>>(
numMultiply,
new ParameterExpression[] { numParam });
Console.Write(lambda1.Compile()(4));
now let's say I want to change this expression tree to Add instead of Multiply
here is the new line :
BinaryExpression numAdd = Expression.Add(numParam,five);
But how can I change the lambda1 so that it will now will use numAdd instead of multiply ?
You just build a new one, and compile it.
Expression<Func<int, int>> lambda1 =
Expression.Lambda<Func<int, int>>(
numAdd,
new ParameterExpression[] { numParam });
From the MSDN page:
Expression trees should be immutable. This means that if you want to modify an expression tree, you must construct a new expression tree by copying the existing one and replacing nodes in it. You can use an expression tree visitor to traverse the existing expression tree.
The "should be" phrase is a little odd but when you look at the API you will see that all relevant properties (Body, Left, Right) are read-only.
I have some code that dynamically builds up some search criteria based on user input, resulting in an Expression<Func<T, bool>> that is passed to the LINQ .Where() method. It works fine when input is present, but when input is not present, I want to create a simple 'return false;' statement so that no results are returned.
Below is my current attempt, but when this is passed to the .Where() method it throws a NotSupportedException "Unknown LINQ expression of type 'Block'."
var parameter = Expression.Parameter(typeof(T), "x");
var falseValue = Expression.Constant(false);
var returnTarget = Expression.Label(typeof (bool));
var returnFalseExpression = Expression.Block(Expression.Return(returnTarget, falseValue), Expression.Label(returnTarget, falseValue));
var lambdaExpression = Expression.Lambda<Func<T, bool>>(returnFalseExpression, parameter);
How can I build a 'return false' expression that can be interpreted by LINQ?
Expression<Func<T, bool>> falsePredicate = x => false;
Can you wrap the entire thing in an if-else expression?
Meaning:
if input
return <your normal code>
else
return false
The return is implicit in expressions; the return value of the expression will simply be the last value. So you could try:
Expression.Condition
(
Expression.NotEqual(input, Expression.Constant("")),
normalSearchExpression,
Expression.Constant(false)
)
That's assuming normalSearchExpression also returns a bool.
I am learning expression trees in C#.
I am stuck now for a while:
string filterString = "ruby";
Expression<Func<string, bool>> expression = x => x == filterString;
How can I construct this expression by code? There is no sample how to capture a local variable. This one is easy:
Expression<Func<string, bool>> expression = x => x == "ruby";
This would be:
ParameterExpression stringParam = Expression.Parameter(typeof(string), "x");
Expression constant = Expression.Constant("ruby");
BinaryExpression equals = Expression.Equal(stringParam, constant);
Expression<Func<string, bool>> lambda1 =
Expression.Lambda<Func<string, bool>>(
equals,
new ParameterExpression[] { stringParam });
The debugger prints the following for (x => x == filterString) :
{x => (x ==
value(Predicate.Program+<>c__DisplayClass3).filterString)}
Thanks for shedding some light on this topic.
Capturing a local variable is actually performed by "hoisting" the local variable into an instance variable of a compiler-generated class. The C# compiler creates a new instance of the extra class at the appropriate time, and changes any access to the local variable into an access of the instance variable in the relevant instance.
So the expression tree then needs to be a field access within the instance - and the instance itself is provided via a ConstantExpression.
The simplest approach for working how to create expression trees is usually to create something similar in a lambda expression, then look at the generated code in Reflector, turning the optimization level down so that Reflector doesn't convert it back to lambda expressions.
This code wraps the expression in a closure Block that treats the local variable as a constant.
string filterString = "ruby";
var filterStringParam = Expression.Parameter(typeof(string), "filterString");
var stringParam = Expression.Parameter(typeof(string), "x");
var block = Expression.Block(
// Add a local variable.
new[] { filterStringParam },
// Assign a constant to the local variable: filterStringParam = filterString
Expression.Assign(filterStringParam, Expression.Constant(filterString, typeof(string))),
// Compare the parameter to the local variable
Expression.Equal(stringParam, filterStringParam));
var x = Expression.Lambda<Func<string, bool>>(block, stringParam).Compile();
An old question but I came to it when trying to do something similar building expressions for Linq-to-entities (L2E) In that case you cannot use Expression.Block as it cannot be parsed down to SQL.
Here is an explicit example following Jon's answer which would work with L2E. Create a helper class to contain the value of the filter:
class ExpressionScopedVariables
{
public String Value;
}
Build the tree thus:
var scope = new ExpressionScopedVariables { Value = filterString};
var filterStringExp = Expression.Constant(scope);
var getVariable = typeof(ExpressionScopedVariables).GetMember("Value")[0];
var access = Expression.MakeMemberAccess(filterStringExp, getVariable);
And then replace the constant in the original code with the member access expression:
BinaryExpression equals = Expression.Equal(stringParam, access);
Expression<Func<string, bool>> lambda1 =
Expression.Lambda<Func<string, bool>>(
equals,
new ParameterExpression[] { stringParam });
I know I can write the following to generate lambda expression:
Expression<Func<string, bool>> lambda = s => s.Length == 5;
But is there any way to automatically generate expression for property? In other words is there strongly-typed analogue of this:
var property = Expression.Property("Name")
This will give you a lambda which returns the Length property:
Expression<Func<string, int>> lambda = s => s.Length;
If you don't want the full lambda, but only the MemberExpression which accesses the property, you can do that:
var propertyExpression = (MemberExpression)lambda.Body;
Expressions<Func<ClassWithProperty, PropertyReturnType>> lambda = C => C.Name;