'Inject' one expression into another - c#

I have one expression that's defined like this:
Expression<Func<T1, T2, bool>> firstExpression;
and another one like this one:
Expression<Func<T1, bool>> secondExpression;
T2 is a value I know, T1 isn't. What I would like is to make the first expression into the second one, given the value of the parameter T2. If it would be regular Linq, it would be this:
var t2 = "Something I know";
secondExpression = t1 => fistExpression(t1, t2);
How would I do this using System.Linq.Expressions?

You can accomplish this with expression visitor:
public static class EmitUtils
{
private class ParameterReplacerVisitor : ExpressionVisitor
{
private ParameterExpression _source;
private Expression _target;
public ParameterReplacerVisitor(ParameterExpression source, Expression target)
{
_source = source;
_target = target;
}
public override Expression Visit(Expression node) =>
node == _source
? _target
: base.Visit(node);
}
public static Expression ReplaceParameter(Expression body, ParameterExpression srcParameter, Expression dstParameter) =>
new ParameterReplacerVisitor(srcParameter, dstParameter).Visit(body);
public static Expression<Func<T1, T3>> BuildClosure<T1, T2, T3>(Expression<Func<T1, T2, T3>> src, T2 closureValue)
{
var constExpression = Expression.Constant(closureValue, typeof(T2));
var body = ReplaceParameter(src.Body, src.Parameters[1], constExpression);
return Expression.Lambda<Func<T1, T3>>(body, src.Parameters[0]);
}
}
Here is sample usage:
[Test]
public void ClosureTest()
{
Expression<Func<int, string, bool>> CheckStringLength = (len, str) => str.Length < len;
var constString = "some string";
var result = EmitUtils.BuildClosure(CheckStringLength, constString);
Assert.That(result.Compile().Invoke(100), Is.True);
}

You can do it by swapping parameter expression with constant expression. Should looks like this
implement custom swap ExpressionVisitor
public class SwapVisitor : ExpressionVisitor
{
public Expression From { get; set; }
public Expression To { get; set; }
public override Expression Visit(Expression node)
{
return node == From ? To : base.Visit(node);
}
}
replace parameter T2 with constant
var swapper = new SwapVisitor
{
From = fistExpression.Parameters[1],
To = Expression.Constant(val)
};
var result = Expression.Lambda<Func<T, bool>>(
swapper.Visit(fistExpression.Body),
fistExpression.Parameters[0]);

Consider the following sample(firstLambda ans secondExpression needed just to see how compiler build the expression)
using System;
using System.Linq.Expressions;
static void Main(string[] args)
{
Expression<Func<string, int, bool>> firstExpression = (a, b) => a == b.ToString();
Func<string, int, bool> firstLambda = (a, b) => a == b.ToString();
Expression<Func<string, bool>> secondExpression = s => firstLambda(s, 45); // this expression I need just to see how it is compiled
var inputParameter = Expression.Parameter(typeof(string), "s");
var invocation = Expression.Invoke(firstExpression, inputParameter, Expression.Constant(47));
var ourBuildExpression = Expression.Lambda<Func<string, bool> > (invocation, new ParameterExpression[] { inputParameter }).Compile();
Console.WriteLine(ourBuildExpression("45"));
Console.WriteLine(ourBuildExpression("47"));
Console.ReadKey();
}
I checked in the debugger watch window the result of Expression<Func<string, bool>> secondExpression = s => firstLambda(s, 45); it was Invoke expression, so I constructed the same manually.
And you can see the test calls return and print False and True as expected.

Related

Modifying predicate expression for wrapping class

I have a repository class that allows for queries using a lambda expression (simplified partial code):
public class SomeRepository<T>: IRepository<T>
{
public IList<T> Find(Expression<Func<T, bool>> filter)
{
return SomeQueryProvider.Where(filter).ToList();
}
}
However, for a specific provider I have the need to wrap the original object in another class:
public class Wrapped<T>
{
public T OriginalObject { get; set; }
}
So in this case, I also need to wrap the incoming predicate expression in another expression:
public class AnotherRepository<T>: IRepository<T>
{
public IList<T> Find(Expression<Func<T, bool>> filter)
{
Expression<Func<Wrapped<T>, bool>> wrappedFilter = ...
return AnotherQueryProvider.Where(wrappedFilter).ToList();
}
}
For example x => x.ParentId == 123 should become x => x.OriginalObject.ParentId == 123.
I can't find examples for this scenario, and I'm having difficulty solving this myself. How can I prepend the predicate expression with the OriginalObject property?
Answering the concrete question.
Given expression
Expression<Func<Wrapped<T>, T>> e1 = w => w.OriginalObject;
converting the expression
Expression<Func<T, bool>> e2 = o => o.ParentId == 123;
to
Expression<Func<Wrapped<T>, T>> e3 = w => w.OriginalObject.ParentId == 123;
is a matter of replacing the o parameter occurrences inside the e2 body with w.OriginalObject (the body of the e1). Something like string replace, but for expressions :)
First you need a method that replaces expression parameter with something else. Here is the one that I use:
public static partial class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
Now the method in question could be like this:
partial class ExpressionUtils
{
public static Expression<Func<Wrapped<T>, TResult>> ToWrapped<T, TResult>(this Expression<Func<T, TResult>> source)
{
Expression<Func<Wrapped<T>, T>> unwrap = w => w.OriginalObject;
var parameter = unwrap.Parameters[0];
var body = source.Body.ReplaceParameter(source.Parameters[0], unwrap.Body);
return Expression.Lambda<Func<Wrapped<T>, TResult>>(body, parameter);
}
}
and the usage
var wrappedFilter = filter.ToWrapped();

Convert Expression<Func<TDerived, out TResult>> to Expression<Func<TBase, out TResult>>

All is said in the title, more precisely I am searching a way to convert an
Expression<Func<TDerived, out bool>> to Expression<Func<TBase, out bool>>,
with TDerived deriving from TBase.
How can I achieve this?
Given an Expression replacer like this one:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
// A simple expression visitor to replace some nodes of an expression
// with some other nodes. Can be used with anything, not only with
// ParameterExpression
public class SimpleExpressionReplacer : ExpressionVisitor
{
public readonly Dictionary<Expression, Expression> Replaces;
public SimpleExpressionReplacer(Expression from, Expression to)
{
Replaces = new Dictionary<Expression, Expression> { { from, to } };
}
public SimpleExpressionReplacer(Dictionary<Expression, Expression> replaces)
{
// Note that we should really clone from and to... But we will
// ignore this!
Replaces = replaces;
}
public SimpleExpressionReplacer(IEnumerable<Expression> from, IEnumerable<Expression> to)
{
Replaces = new Dictionary<Expression, Expression>();
using (var enu1 = from.GetEnumerator())
using (var enu2 = to.GetEnumerator())
{
while (true)
{
bool res1 = enu1.MoveNext();
bool res2 = enu2.MoveNext();
if (!res1 || !res2)
{
if (!res1 && !res2)
{
break;
}
if (!res1)
{
throw new ArgumentException("from shorter");
}
throw new ArgumentException("to shorter");
}
Replaces.Add(enu1.Current, enu2.Current);
}
}
}
public override Expression Visit(Expression node)
{
Expression to;
if (node != null && Replaces.TryGetValue(node, out to))
{
return base.Visit(to);
}
return base.Visit(node);
}
}
now we can, given
public class Base
{
public int ValueBase { get; set; }
}
public class Derived : Base
{
public int ValueDerived { get; set; }
}
and a
Expression<Func<Derived, bool>> exp = x => x.ValueBase == 0;
then
ParameterExpression parOld = exp.Parameters[0];
ParameterExpression parNew = Expression.Parameter(typeof(Base));
// Replace the parOld with the parNew
Expression body2 = new SimpleExpressionReplacer(parOld, parNew).Visit(exp.Body);
// Note that we have to rebuild the Expression.Lambda<>
Expression<Func<Base, bool>> expNew = Expression.Lambda<Func<Base, bool>>(body2, parNew);
This will produce a
Expression<Func<Base, bool>> exp = x => x.ValueBase == 0;
Note that if you want instead to do:
Expression<Func<Derived, bool>> exp = x => x.ValueDerived == 0;
to
Expression<Func<Base, bool>> exp = x => ((Derived)x).ValueDerived == 0;
then you need something like:
ParameterExpression parOld = exp.Parameters[0];
ParameterExpression parNew = Expression.Parameter(typeof(Base));
UnaryExpression convert = Expression.Convert(parNew, typeof(Derived));
Expression body2 = new SimpleExpressionReplacer(parOld, convert).Visit(exp.Body);
Expression<Func<Base, bool>> expNew = Expression.Lambda<Func<Base, bool>>(body2, parNew);
You need to wrap the inner expression. Something like
var argument = Expression.Parameter(typeof(TDerived));
Expression.Lambda<Func<TDerived, bool>>
(
Expression.Invoke(innerExpression, argument),
argument
);
Of course, depending on the direction, you might need an explicit cast on the argument to innerExpression - this is quite simple, just use Expression.Cast.
EDIT:
To accomodate for your edit, the inverted variant:
var argument = Expression.Parameter(typeof(TBase));
Expression.Lambda<Func<TBase, bool>>
(
Expression.Invoke(innerExpression, Expression.Convert(argument, typeof(TDerived))),
argument
);
Note that this will obviously only work if the runtime type of the parameter is derived from TDerived.

DLINQ projecting into concrete types with expression trees

I have an expression tree for Purchase class
public static readonly Expression<Func<Purchase, double?>> CurrentPaidSumLambda =
p => (double?)p.Payments
.Where(pa => pa.Status == SystemConstants.PaymentStatus.Paid)
.Sum(pa => pa.Sum);
I wish to create projection into a type PurchaseSummaryInfo like this
var ps = Db.Purchases.Select(p =>
new PurchaseSummaryInfo
{
paidSum = (double?)p.Payments
.Where(pa => pa.Status == SystemConstants.PaymentStatus.Paid)
.Sum(pa => pa.Sum) ?? 0
});
But to use my "pre-canned" expression tree.
Can it be done, and if yes - how?
We'll need a Combine method. This method will take an expression that accepts a value and computes an intermediate result, and then a second expression that accepts the same input as the first expression, accepts the intermediate result as a second parameter, and then computes a new value.
public static Expression<Func<TFirstParam, TResult>>
Combine<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TFirstParam, TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], param)
.Replace(second.Parameters[1], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
As an implementation, it relies on the ability to replace all instances of one expression with another, which can be done using this:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
So now we can write:
var ps = Db.Purchases.Select(CurrentPaidSumLambda.Combine((p, sum) =>
new PurchaseSummaryInfo
{
paidSum = sum ?? 0
});

Partial application of an expression tree

I have an Expression in the following form:
Expression<Func<T, bool>> predicate = t => t.Value == "SomeValue";
Is it possible to create a 'partially applied' version of this expression:
Expression<Func<bool>> predicate = () => t.Value == "SomeValue";
NB This expression is never actually compiled or invoked, it is merely inspected to generate some SQL.
This could be easily achieved by writing a custom ExpressionVisitor and replacing the parameter with a constant expression that you have captured in a closure:
public class Foo
{
public string Value { get; set; }
}
public class ReplaceVisitor<T> : ExpressionVisitor
{
private readonly T _instance;
public ReplaceVisitor(T instance)
{
_instance = instance;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return Expression.Constant(_instance);
}
}
class Program
{
static void Main()
{
Expression<Func<Foo, bool>> predicate = t => t.Value == "SomeValue";
var foo = new Foo { Value = "SomeValue" };
Expression<Func<bool>> result = Convert(predicate, foo);
Console.WriteLine(result.Compile()());
}
static Expression<Func<bool>> Convert<T>(Expression<Func<T, bool>> expression, T instance)
{
return Expression.Lambda<Func<bool>>(
new ReplaceVisitor<T>(instance).Visit(expression.Body)
);
}
}
I think this should work:
Expression predicate2 = Expression.Invoke(predicate, Expression.Constant(new T() { Value = "SomeValue"}));
Expression<Func<bool>> predicate3 = Expression.Lambda<Func<bool>>(predicate2);
Don't know if this is easily parseable to generate SQL however (it works when compiled - I tried).

Converting 2 argument Lambda expression to 1 argument Lambda expression (specifying one argument)

I have expression
Expression<Func<Car, Driver, bool>> CanBeDrivenBy =
(car, driver) => car.Category == 'B' && driver.Age > 18;
and I want to get cars which can be driven by some driver
IQueryable<Cars> cars = ...;
Driver driver = ...;
cars.Where(CanBeDrivenBy); // Fail, expecting Expression<Func<Car, bool>>
So I need to convert Expression<Func<Car, Driver, bool>> to Expression<Func<Car, bool>> (specify driver)
Yes I can use
cars.Where(c => c.Category == 'B' && driver.Age > 18);
but I need solution with expression which can be changed dynamicly. And I need to pass Expression (using entity framework)
you can reuse modified version of source expressions body
using System;
using System.Linq.Expressions;
public class Program
{
public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument)
{
Expression arg2 = Expression.Constant(argument, typeof (T2));
Expression newBody = new Rewriter(source.Parameters[1], arg2).Visit(source.Body);
return Expression.Lambda<Func<T1, TResult>>(newBody, source.Parameters[0]);
}
public static void Main(string[] args)
{
Expression<Func<string, string, int>> f = (a, b) => a.Length + b.Length;
Console.WriteLine(f); // (a, b) => (a.Length + b.Length)
Console.WriteLine(Bind2nd(f, "1")); // a => (a.Length + "1".Length)
}
#region Nested type: Rewriter
private class Rewriter : ExpressionVisitor
{
private readonly Expression candidate_;
private readonly Expression replacement_;
public Rewriter(Expression candidate, Expression replacement)
{
candidate_ = candidate;
replacement_ = replacement;
}
public override Expression Visit(Expression node)
{
return node == candidate_ ? replacement_ : base.Visit(node);
}
}
#endregion
}
This WORKS
I wrote this function to reduce number of arguments from 2 to 1 by specifying the second argument.
public static Expression<Func<T1, TResult>> Bind2nd<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> source, T2 argument)
{
Expression arg2 = Expression.Constant(argument, typeof(T2));
var arg1 = Expression.Parameter(typeof(T1));
return Expression.Lambda<Func<T1, TResult>>(Expression.Invoke(source, arg1, arg2), arg1);
}
Usage:
IQueryable<Car> cars = ...;
Driver driver = ...;
cars.Where(Bind2nd(CanBeDrivenBy, driver));
arg1 is temporary storage between calls.
Is there any system equivalent function?

Categories