Linq - Creating Expression<T1> from Expression<T2> - c#

I have a predicate Expression<Func<T1, bool>>
I need to use it as a predicate Expression<Func<T2, bool>> using the T1 property of T2 I was trying to think about several approches, probably using Expression.Invoke but couln;t get my head around it.
For reference:
class T2 {
public T1 T1;
}
And
Expression<Func<T1, bool>> ConvertPredicates(Expression<Func<T2, bool>> predicate) {
//what to do here...
}
Thanks a lot in advance.

Try to find the solution with normal lambdas before you think about expression trees.
You have a predicate
Func<T1, bool> p1
and want a predicate
Func<T2, bool> p2 = (x => p1(x.T1));
You can build this as an expression tree as follows:
Expression<Func<T2, bool>> Convert(Expression<Func<T1, bool>> predicate)
{
var x = Expression.Parameter(typeof(T2), "x");
return Expression.Lambda<Func<T2, bool>>(
Expression.Invoke(predicate, Expression.PropertyOrField(x, "T1")), x);
}

Related

How to filter IQueryable dynamically by generic field

I'm trying to make a IDictionary<TKey, List<TSource>> class where I can decide the key by a func. I have managed to build the class with arrays like this (functions are simplified for examples sake):
private List<TSource> Filter(TKey key, Func<TSource, TKey> keySelector)
{
IQueryable<TSource> source = GetSource(); // It's there
IQueryable<TSource> filtered = source.Where(
x => keySelector.Invoke(x).Equals(key)
);
return filtered.ToList();
}
But this works only with arrays and such, not with linq-to-sql. I understand this can be done with expressions, but thats mostly beyond me. I have googled and come up with the following functions:
private List<TSource> Filter(TKey key, Expression<Func<TSource, TKey>> keySelector)
{
IQueryable<TSource> source = GetSource();
Func<TSource, bool> compiledKeyFilter = GetFilter(keySelector);
IEnumerable<TSource> filtered = source.Where(compiledKeyFilter);
return filtered.ToList();
}
private Func<TSource, bool> GetFilter(Expression<Func<TSource, TKey>> expr)
{
if (this.filter == null)
{
var invokedExpr = Expression.Invoke(expr, expr.Parameters.Cast<Expression>());
var lamda = Expression.Lambda<Func<TSource, bool>>(
Expression.Call(expr.Body, typeof(TKey).GetMethod("Equals", new[] { typeof(TKey) }), invokedExpr),
expr.Parameters
);
this.filter = lamda.Compile();
}
return this.filter;
}
This currently returns all rows in the source. The expression should be reusable, not just for one-time execution. I found the following from SO (Dynamically generated lookup key for IQueryable), what I'm doing is quie similar. It works, but I'm unable to combine it with the compiled approach:
private Expression<Func<TSource, bool>> MakeFilterExpression(TKey key)
{
var param = Expression.Parameter(typeof(TSource));
return Expression.Lambda<Func<TSource, bool>>(
Expression.Equal(
Expression.Invoke(keySelector, param),
Expression.Constant(key)
),
param
);
}
So I'm trying to come up with a class that I could use like this:
// Inside MyCache there would be something close to this:
class MyCache
{
private Func<TSource, bool> filter;
public MyCache(Expression<Func<TSource, TKey>> func)
{
this.filter = MakeFilter(func);
}
private Func<TSource, bool> MakeFilter(Expression<Func<TSource, TKey>> func)
{
// magic
}
public List<TSource> GetByKey(TKey key)
{
return GetSource().Where(this.filter(key)).ToList();
}
}
// This is my class where I give my func to determine the key in ctor.
var cache = new MyCache<MySource>(x => x.myField);
var list1 = cache.GetByKey(3); // Now I have list to iterate.
var list2 = cache.GetByKey(4); // Here's another list.
Is it even possible to compile that into a reusable function? Help?!
If I understand your question correctly, then you are trying to come up with a version of the Filter method that works with LINQ-to-SQL queries given an Expression<Func<TSource, TKey>> key selector.
You can use the LINQKit library to help you with that. It allows you to invoke one expression from another one and then "expand" the result expression.
Here is how you would code your Filter method with the help of LINQKit:
private static List<TSource> Filter<TSource,TKey>(
TKey key,
Expression<Func<TSource, TKey>> keySelector)
{
IQueryable<TSource> source = GetSource<TSource>(); // It's there
Expression<Func<TSource, bool>> predicate = x => keySelector.Invoke(x).Equals(key);
//LINQ-to-SQL cannot translate `Invoke` into SQL. However, after invoking this line
//LINQKit would flatten the expression so that it contains something like
//x => x.Age.Equals(5) (for a keySelector of value x => x.Age and key of value 5)
predicate = predicate.Expand();
IQueryable<TSource> filtered = source.Where(predicate);
return filtered.ToList();
}

Creating Expression<Func<T, bool>> predicate with just LambaExpression and comparison value

I need to create a Expression<Func<T, bool>>, but all I have is a LambaExpression of the property to compare and the value to use for the comparison.
This is what the predicate would look like if I hard code it, and this is what I need to achieve but don't know how.
string comparisonValue = "something";
Expression<Func<Person, bool>> predicate = person => person.Name == comparisonValue;
I have the following:
LambdaExpression expression = PropertyExpression<Person>(t => t.Name);
Is there a way to generate the hard coded predicate like the above with just a property LambdaExpression and the value to compare?
I've tried using LambdaExpression.Equal(), but cannot get it to work.
You can implement this as follows.
Expression<Func<TSource, bool>> EqualToExpression<TSource, TValue>(
Expression<Func<TSource, TValue>> selectValue, TValue targetValue)
{
return Expression.Lambda<Func<TSource, bool>>(
Expression.Equal(
selectValue.Body,
Expression.Constant(targetValue)),
selectValue.Parameters);
}
Use it as follows.
Expression<Func<Person, string>> selectName = p => p.Name;
Expression<Func<Person, bool>> compareName = EqualToExpression(selectName, "John");

Extending an access expression to check for value

I'm currently trying to wrestle with expression trees to make a bit of magic happen, but I keep hitting error after error.
I've got some properties like this on some of my domain objects (Entity Framework)
Expression<Func<DomainObject, LinkedDomainObject>> IncludeExpr
{
get {
return o => o.SomeLinkedObject;
}
}
and another expression that checks that linked object for equality on some property (e.g. ID).
I did have an expression that also checked that linked object for being null, and that way I could compose a NotNull and Matched ID expression by inverting the null check expression and combining it via AndAlso with the ID check expression.
I want to take the o => o.SomeLinkedObject expression and linkedObject => linkedObject.ID == idVar expressions and mash them together to effectively get:
o => o.LinkedObject != null && o.LinkedObject.Id == idVar
But I can't for the life of me work out how I'd get an expression tree together based on those two separate expressions.
We can take a moment to create a helper method that can make solving this problem very straightforward. If we create a method that lets us compose expressions as easily as we can compose delegates, this becomes very easy. Our Compose method will accept an expression, and another that takes the output of the first and transforms it into something else, creating a new expression that can transform something of the type of the input of the first into the output of the second:
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<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], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
This is dependent on the following method to replace all instances of one expression with another:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
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);
}
}
Now we can create an IsNotNull transformation very easily:
public static Expression<Func<TSource, bool>> IsNotNull<TSource, TKey>(
this Expression<Func<TSource, TKey>> expression)
{
return expression.Compose(key => key != null);
}
As for And-ing two expressions together, the easiest option if using a LINQ query provider is to just call Where on each expression separately, if that's an option. If not, you can use a PrediacteBuilder to And or Or two expressions together:
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(
expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(
expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}
}

Negating Func<T, bool> in lambda expression [duplicate]

This question already has answers here:
Is there any way to negate a Predicate?
(2 answers)
Closed 9 years ago.
Func<T, bool> expr = x => x.Prop != 1;
somelist = somelist.Where(expr);
So far so good. But I would like to negate expr like this:
somelist = somelist.Where(!expr);
Which result in a compile error: Cannot apply ! operator to operand of type Func<T, bool>.
Do I have to create another expression variable for this?
Func<T, bool> expr2 = x => x.Prop == 1;
Func<T, bool> expr = x => x.Prop != 1;
Func<T, bool> negativeExpr = value => !expr(value);
or
somelist = somelist.Where(value => !expr(value));
When using expression trees the following will do the trick:
Expression<Func<T, bool>> expr = x => x.Prop != 1;
var negativeExpr = Expression.Lambda<Func<T, bool>>(
Expression.Not(expr.Body),
expr.Parameters);
somelist = somelist.Where(negativeExpr);
To make your life easier, you can create the following extension methods:
public static Func<T, bool> Not<T>(
this Func<T, bool> predicate)
{
return value => !predicate(value);
}
public static Expression<Func<T, bool>> Not<T>(
this Expression<Func<T, bool>> expr)
{
return Expression.Lambda<Func<T, bool>>(
Expression.Not(expr.Body),
expr.Parameters);
}
Now you can do this:
somelist = somelist.Where(expr.Not());
I'm just going to throw this out there as a silly answer. Just to be clear: I would not do this, and I do not recommend that anyone does this. :)
I kind of wanted to see if it was possible to get the somelist.Where(!expr) syntax or something like it.
Well I succeeded, and I hate myself.
var expr = N.egatable<MyClass>(x => x.Prop != 1);
somelist = someList.Where(!expr);
The N.egatable was just a small convenience syntax helper and largely unnecessary (EDIT: I wanted to avoid having to explicitly define MyClass or somehow make the instantiation of the object wrapper hidden, but couldn't quite get there and thought maybe someone would have a better idea):
public static class N
{
public static Negator<T> egatable<T>(Func<T, bool> underlyingFunction)
{
return new Negator<T>(underlyingFunction);
}
}
Negator<T> is where the real "magic" happens:
public class Negator<T>
{
private Func<T, bool> UnderlyingFunction;
public Negator(Func<T, bool> underlyingFunction)
{
this.UnderlyingFunction = underlyingFunction;
}
public static implicit operator Func<T, bool>(Negator<T> neg)
{
return v => neg.UnderlyingFunction(v);
}
public static Negator<T> operator !(Negator<T> neg)
{
return new Negator<T>(v => !neg.UnderlyingFunction(v));
}
}
First the ! operator overload performs the function negation (just as in this answer), then the implicit conversion operator to Func<T, bool> lets it pass in to the Where extension method.
Perhaps very silly is you can keep flipping it back and forth like this:
somelist = someList.Where(!!expr);
somelist = someList.Where(!!!expr);
somelist = someList.Where(!!!!expr);
somelist = someList.Where(!!!!!expr);
somelist = someList.Where(!!!!!!expr); //oh my what
So again... please don't do this. :) Definitely stick to the proper/sane way of doing things as in Steven's answer.
EDIT: Here's an implementation using expressions which works the exact same way in terms of syntax usage. Not sure if it's "correct", and haven't tested it against Entity Framework:
public class ExpressionNegator<T>
{
private Expression<Func<T, bool>> UnderlyingExpression;
public ExpressionNegator(Expression<Func<T, bool>> underlyingExpression)
{
this.UnderlyingExpression = underlyingExpression;
}
public static implicit operator Func<T, bool>(ExpressionNegator<T> neg)
{
return neg.UnderlyingExpression.Compile();
}
public static implicit operator Expression<Func<T, bool>>(ExpressionNegator<T> neg)
{
return neg.UnderlyingExpression;
}
public static ExpressionNegator<T> operator !(ExpressionNegator<T> neg)
{
var originalExpression = neg.UnderlyingExpression;
Expression<Func<T, bool>> negatedExpression = originalExpression.Update(
Expression.Not(originalExpression.Body),
originalExpression.Parameters);
return new ExpressionNegator<T>(negatedExpression);
}
}

Convert Predicate<T> to Expression<Func<T, bool>>

Is possible to convert a Predicate<T> to Expression<Func<T, bool>> in some way?
I would like to use the next IQueryable function using the filters of the my ICollectionView:
public static System.Linq.IQueryable<TSource> Where<TSource>(this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, bool>> predicate)
Thanks
Something like this?
Predicate<string> predicate = input => input.Length > 0;
Expression<Func<string, bool>> expression = (input) => predicate(input);
You can probably make an extension Where method for your ICollectionView which takes a predicate, converts it to an Expression like this, and then call the Where method provided by Linq.
public static IQueryable<T> Where(this IQueryable<T> source, Predicate<T> predicate)
{
return source.Where(x => predicate(x));
}
In theory it is possible to convert a delegate 'back' to an expression, because you can request the emitted IL of a delegate, which gives you the information you need to transform it back.
However, it's for a reason that neither LINQ to SQL and Entity Framework do this. It is complex, fragile, and performance intensive to do so.
So the short answer is, you can't transform it to an expression.
namespace ConsoleApplication1
{
static class Extensions
{
public static Expression<Func<T, bool>> ToExpression<T>(this Predicate<T> p)
{
ParameterExpression p0 = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, bool>>(Expression.Call(p.Method, p0),
new ParameterExpression[] { p0 });
}
}
}

Categories