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.
Related
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
);
I am trying to familiarize myself with Expression Trees, and I'm hitting a wall. I want to be able to dynamically create LINQ to XML queries, so I am trying to familiarize myself with Expression Trees. I started with a simple LINQ to XML statement that I want to be able to generate dynamically:
// sample data
var sampleData = new XElement("Items",
new XElement("Item", new XAttribute("ID", 1)),
new XElement("Item", new XAttribute("ID", 2)),
new XElement("Item", new XAttribute("ID", 3))
);
// simple example using LINQ to XML (hard-coded)
var resultsStatic = from item in sampleData.Elements("Item")
where item.Attribute("ID").Value == "2"
select item;
// trying to recreate the above dynamically using expression trees
IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable<XElement>();
ParameterExpression alias = Expression.Parameter(typeof(XElement), "item");
MethodInfo attributeMethod = typeof(XElement).GetMethod("Attribute", new Type[] { typeof(XName) });
PropertyInfo valueProperty = typeof(XAttribute).GetProperty("Value");
ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");
Expression methodCall = Expression.Call(alias, attributeMethod, new Expression[] { attributeParam });
Expression propertyAccessor = Expression.Property(methodCall, valueProperty);
Expression right = Expression.Constant("2");
Expression equalityComparison = Expression.Equal(propertyAccessor, right);
var resultsDynamic = queryableData.Provider.CreateQuery(equalityComparison);
The error that I get when calling CreateQuery is 'Argument expression is not valid'. The debug view for equalityComparison shows '(.Call $item.Attribute($ID)).Value == "2"'. Can someone identify what I am doing incorrectly?
To better understand what's going on, always start with method syntax of the desired query. In your case it is as follows (I'm specifically including the types although normally I would use var):
IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable();
IQueryable<XElement> queryStatic = queryableData
.Where((XElement item) => item.Attribute("ID").Value == "2");
Now let see what you have.
First, the attributeParam variable
ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");
As you can see from the static query, there is no lambda parameter for attribute name - the only supported (and required) parameter is the item (which in your code is represented by the alias variable). So this should be ConstantExpression of type XName with value "ID":
var attributeParam = Expression.Constant((XName)"ID");
Second, the equalityComparison variable. All it contains is the item.Attribute("ID").Value == "2" expression. But Where method requires Expression<Func<XElement, bool>>, so you have to create such using the equalityComparison as body and alias as parameter:
var predicate = Expression.Lambda<Func<XElement, bool>>(equalityComparison, alias);
Finally you have to call Where method. You can do that directly:
var queryDynamic = queryableData.Where(predicate);
or dynamically:
var whereCall = Expression.Call(
typeof(Queryable), "Where", new Type[] { queryableData.ElementType },
queryableData.Expression, Expression.Quote(predicate));
var queryDynamic = queryableData.Provider.CreateQuery(whereCall);
You can take a look at the used Expression methods documentation for further details what they do.
Linq to XML works in memory, meaning you do not nead Expression trees, just use the Enumerable extension methods. Makes your code much simplier and easier to read!!!
I have an expression of type Expression<Func<TOwner, object>> that was created using lambda (syntax). It has member-access expression somewhere in the body. I would like to create expression that selects another property of the mentioned expression's result.
I terms of C# it should look like this:
Expression<Func<MyClient, object>> exStartingPath = x => x.Address;
Expression<Func<MyClient, object>> exExtendedPath = ExtendSelection(exStartingPath, "Street");
//exExtendedPath should be equivalent to x => x.Address.Street
How should ExtendSelection(...) be implemented? Should I decompose already existing expression and compose new one using some traversing technique or is there any API that can just 'append' member selection?
Just grab the body of the lambda, apply the member access to that, and then wrap the whole thing back up into a new lambda.
public static Expression<Func<TSource, TTarget>> ExtendSelection<TSource, TTarget>(
Expression<Func<TSource, TTarget>> expression, string member)
{
var body = Expression.PropertyOrField(expression.Body, member);
return Expression.Lambda<Func<TSource, TTarget>>(body, expression.Parameters);
}
Given two generic type variables, how do I compile a system.linq.expression tree to multiply them? It's perfectly acceptable if the expression throws an exception if the two types do not have a valid operator * between them.
I chose System.Linq.Expression because I recall seeing it done that way on here, but not enough about how.
Thanks.
Edit: I chose compiling a Linq expression for speed; this should be as fast as reasonably possible.
You can find out how to do this by writing the following code:
Expression<Func<int, int, int>> multiply =
(left, right) => left * right;
Compiling it down to an assembly and use a IL deassembler (such as Reflector) to look at the code the C# compiler produced.
With the given example, the C# compiler will generate something like this:
var left = Expression.Parameter(typeof(int), "left");
var right = Expression.Parameter(typeof(int), "right");
var multiply = Expression.Lambda<Func<int, int, int>>(
Expression.Multiply(left, right),
new ParameterExpression[] { left, right });
And this is exactly what you need to do to specify a multiply expression.
When placed in a generic method, it might look something like this:
public static Func<T, T, T> BuildMultiplier<T>()
{
var left = Expression.Parameter(typeof(T), "left");
var right = Expression.Parameter(typeof(T), "right");
var multiply = Expression.Lambda<Func<T, T, T>>(
Expression.Multiply(left, right),
new ParameterExpression[] { left, right });
return multiply.Compile();
}
Try something like this:
var left = Expression.Parameter(typeof(T), "left");
var right = Expression.Parameter(typeof(T), "right");
var body = Expression.Multiply(left, right);
return Expression.Lambda<Func<T, T, TResult>>(body, left, right);
If there is no valid multiplication operator for type T, the Expression.Multiply line will throw an exception.
I chose System.Linq.Expression
Just to be clear: there's another easy way:
public static T Multiply<T>(T x, T y) {
return ((dynamic)x) * y;
}
and offload the work (including cache) to the framework. Another option - MiscUtil has generic operator support that wraps this up - downloadable here.
So I'm trying to optimize a query that does a text search on 1000s of rows and displays 100s of them. To do so, I'm trying to understand some code from Microsoft's 101 Sample Queries (found here).
Here is the code I wish to understand:
[Category("Advanced")]
[Title("Dynamic query - Where")]
[Description("This sample builds a query dynamically to filter for Customers in London.")]
public void LinqToSqlAdvanced02()
{
IQueryable<Customer> custs = db.Customers;
ParameterExpression param = Expression.Parameter(typeof(Customer), "c");
Expression right = Expression.Constant("London");
Expression left = Expression.Property(param, typeof(Customer).GetProperty("City"));
Expression filter = Expression.Equal(left, right);
Expression pred = Expression.Lambda(filter, param);
Expression expr = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(Customer) }, Expression.Constant(custs), pred);
IQueryable<Customer> query = db.Customers.AsQueryable().Provider.CreateQuery<Customer>(expr);
ObjectDumper.Write(query);
}
So...I realize this is esoteric, but why does Expression.Call() need the DbSet reference it's passed to CreateQuery as <T>?
I believe what you're asking is why the third parameter (array of types) is needed in Expression.Call because if you did it through code, you'd only have to do this:
custs.Where(pred);
The reason why the code works without the generic parameter is because of implicit typing, where the compiler translates that automatically to:
custs.Where<Customer>(pred);
After it translates it, the actual bytecode contains the call with the generics specified. When you build the Expression, you don't have all the niceties like implicit typing, so you have to specify exactly what gets called.