Extract piece of lambda for expression in select - c#

I can extract and reuse entire expression like that:
Expression<Func<User, int>> userExpression = x => x.Roles.Count()
but is it possible to extract some how only x.Roles.Count() part and use that in context of Expression<Func<User, T>>
Thing that I am trying to achieve is reuse that part across different selects like:
users.Select(x => new AnotherClass { RoleCount = roleCountPartOfExpression})
and
users.Select(x => new OneMoreAnotherClass
{
AnotherProperty = roleCountPartOfExpression
});
So what roleCountPartOfExpression is supposed to be in this case should be supported in LINQ to Entities (so creating a method where I will pass User where will be return user.Roles.Count() will not work) also I cant create expression for select like Expression<Func<User, AnotherClass>> because in that case I will need to create Expression<Func<User, OneMoreAnotherClass>> and that will break my "reusability" goal.

If you compile to a Func<User, int>, you can call it in other areas like so:
Expression<Func<User, int>> userExpression = x => x.Roles.Count();
Func<User,int> userFunc = userExpression.Compile();
users.Select(x => new AnotherClass { RoleCount = userFunc(x) });
Or simply define as a Func to begin with:
Func<User,int> userFunc = x => x.Roles.Count();
Is this using Linq-to-Objects or something else? If you need to keep it as an Expression because the Expression gets converted into something else (like a SQL call), you can use LinqKit's AsExpandable like so:
public static Expression<Func<User,int>> RoleCount()
{
return u => u.Roles.Count();
}
public static void DoStuff()
{
var roleCounter = RoleCount();
var query = users.AsExpandable()
.Select(u => roleCounter.Invoke(u));
}

We can create a Combine method that is able to take a selector for an object and then another selector that also takes the output of the first selector to produce a final result:
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);
}
This uses the following helper method to replace all instance of one expression with another:
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);
}
Now we can write:
Expression<Func<User, int>> userExpression = x => x.Roles.Count()
var query = users.Select(userExpression.Combine((x, count) =>
new OneMoreAnotherClass { AnotherProperty = count});

You can do this with a closure:
User x = z; // assign local value
var countX = () => x.Roles.Count();
now this will work:
users.Select(x => new AnotherClass { RoleCount = countX() })

Related

EFcore where clause with custom function to determine type of comparison

What I'm trying to do
I have a repository function that I want to be able support searching by string Equals, Contains, StartsWith, EndsWith. I've created a simple extension method that wraps around these string functions, but EFCore seems unable to translate this.
Are there are any alternative, reusable approaches similar to this?
How I'm trying to do it
public enum StringComparisonType
{
Equals,
Contains,
BeginsWith,
EndsWith
}
public static bool CompareTo(this string inputText, string comparisonText, StringComparisonType comparisonType) => comparisonType switch
{
StringComparisonType.Equals => inputText.Equals(comparisonText),
StringComparisonType.BeginsWith => inputText.StartsWith(comparisonText),
StringComparisonType.Contains => inputText.Contains(comparisonText),
StringComparisonType.EndsWith => inputText.EndsWith(comparisonText),
_ => throw new NotImplementedException($"{nameof(StringComparisonType)} {comparisonType} not currently supported.")
};
var searchText = "hello";
var comparison = StringComparisonType.BeginsWith;
_context.Records.Where(r => r.Text.CompareTo(searchText, comparison))
The problem with the approach
This throws an error along the lines of:
The LINQ expression could not be translated
Alternative approach
The only alternative I've found that works is just inlining the logic to determine the type of comparison to apply, but this is horrible to read, horrible to write, and is not reusable, e.g.
_context.Records
.Where(r => comparison == StringComparisonType.Equals
? r.Text.Equals(searchText)
: comparison == StringComparisonType.BeginsWith
? r.Text.StartsWith(searchText)
: comparison == StringComparisonType.EndsWith
? r.Text.EndsWith(searchText)
: r.Text.Contains(searchText))
I'm currently using EFCore 7.
If you use it on predefined type (be Record in example) try something like this:
public static IQueryable<Record> WhereCompare(this IQueryable<Record> query, string comparisonText, StringComparisonType comparisonType) => comparisonType switch
{
StringComparisonType.Equals => query.Where(r => r.Text.Equals(comparisonText)),
StringComparisonType.BeginsWith => query.Where(r => r.Text.StartsWith(comparisonText)),
StringComparisonType.Contains => query.Where(r => r.Text.Contains(comparisonText)),
StringComparisonType.EndsWith => query.Where(r => r.Text.EndsWith(comparisonText)),
_ => throw new NotImplementedException($"{nameof(StringComparisonType)}
{comparisonType} not currently supported.")
}
And then use it like this:
var result = _context.Records.WhereCompare(searchText, comparison).ToList();
Generic method
Maybe this can be done easier, but let's do this. First implement Compose function (combine sequence of expressions into one):
using System;
using System.Linq;
using System.Linq.Expressions;
...
private static Expression<Func<TSource, TResult>> Compose<TSource, TIntermediate, TResult>(
this Expression<Func<TSource, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TSource));
var intermediateValue = first.Body.ReplaceParameter(first.Parameters[0], param);
var body = second.Body.ReplaceParameter(second.Parameters[0], intermediateValue);
return Expression.Lambda<Func<TSource, TResult>>(body, param);
}
private static Expression ReplaceParameter(this Expression expression,
ParameterExpression toReplace,
Expression newExpression)
{
return new ParameterReplaceVisitor(toReplace, newExpression)
.Visit(expression);
}
private class ParameterReplaceVisitor : ExpressionVisitor
{
private ParameterExpression from;
private Expression to;
public ParameterReplaceVisitor(ParameterExpression from, Expression to)
{
this.from = from;
this.to = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node == from ? to : node;
}
}
With this methods we can now create this:
public static IQueryable<T> WhereCompare<T>(this IQueryable<T> query, Expression<Func<T, string>> selector, string comparisonText, StringComparisonType comparisonType)
{
var filter = Compose<T, string, bool>(selector, WhereCompareSelector<T>(comparisonText, comparisonType));
return query.Where(filter);
}
public static Expression<Func<string, bool>> WhereCompareSelector<T>(string comparisonText, StringComparisonType comparisonType) => comparisonType switch
{
StringComparisonType.Equals => r => r.Equals(comparisonText),
StringComparisonType.BeginsWith => r => r.StartsWith(comparisonText),
StringComparisonType.Contains => r => r.Contains(comparisonText),
StringComparisonType.EndsWith => r => r.EndsWith(comparisonText),
_ => throw new NotImplementedException($"{nameof(StringComparisonType)}{comparisonType} not currently supported.")
};
Usage:
var result = _context.Records.WhereCompare(t => t.Text, searchText, comparison).ToList();

Trouble with building a C# EntityFramework IQueryable Expression

So I'm attempting to build a semi complication Search expression, but I'm stuck trying to create a basic one. The expressions being used for getValueExpression look something like:
x => x.PropertyA != null ? x.PropertyA.ToShortDateString() : "" //nullable datetime
x => x.PropertyB //string property
x => x.PropertyC != null x.PropertyC.ToString() : "" //nullable int
Here is my function code, it currently errors when getValueExpression being of type Func that can't be compared to a string, which makes perfect sense and I understand why that is, but I'm having trouble figuring out how to make an expression that gets the value of getValueExpression to compare to the value being searched for. Any help or leads in the right direction would be greatly appreciated.
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> getValueExpression, string searchOption, string searchValue)
{
var searchValueExpression = Expression.Constant(searchValue);
var comparisonExpression = Expression.Equal(getValueExpression, searchValueExpression);
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(comparisonExpression);
return source.Where(lambdaExpression);
}
I've attempted similar things like this, but have met failure with incorrect arguments amount exception:
var getValueExpressionValue = Expression.Call(getValueExpression.Compile().Method, parameterValueExpression);
Here is a method that will let you compose expressions; that is to say you can use the output of one expression as the input of another, creating a new expression taking the input that the first takes and the output that the second takes:
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);
}
Which uses the following method to replace one expression with another:
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);
}
This lets you write:
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, string>> getValueExpression,
string searchOption,
string searchValue)
{
var predicate = getValueExpression.Compose(value => value == searchValue);
return source.Where(predicate);
}
Here is how you can do it :
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> getValueExpression, string searchOption, string searchValue)
{
// const searchValue
var searchValueExpression = Expression.Constant(searchValue);
// parameter x
var parameterExpression = Expression.Parameter(typeof(TSource));
// func(x)
var parameterGetValueExpression = Expression.Invoke(getValueExpression, parameterExpression);
// func(x) == searchValue
var comparisonExpression = Expression.Equal(parameterGetValueExpression, searchValueExpression);
// x => func(x) == searchValue
var lambdaExpression = Expression.Lambda<Func<TSource, bool>>(comparisonExpression, parameterExpression);
return source.Where(lambdaExpression);
}

Adding Expression argument as property in LINQ to Entities

Using EF6, how would I bind a given Expression<Func<Row, string>> argument to an existing select expression, without having to rewrite every property binding using expression trees?
public IEnumerable<RowModel> GetRowModels(Expression<Func<Row, string>> textExpr)
{
return from row in MyDatabaseContext.MyTable
select new RowModel
{
RowID = row.ID,
CreatedDate = row.CreatedDate,
AnotherProperty = row.AnotherProperty,
Text = textExpr, // how do I bind this expression?
Value = row.OtherStuff.Where(os => os.ShouldUse).Select(os => os.Value).FirstOrDefault(),
AnotherValue = row.OtherStuff.Where(os => os.ShouldUseAgain).Select(os => os.Value).FirstOrDefault()
};
}
What you need here is a method to combine several expressions. Specifically, what we would like is a way to take an expression that maps a value and then also accept an expression that accepts the input of the first expression, and the output of the first expression, and computes a new value.
As an implementation of this method we can replace all instances of "the result of the first function" with the body of the first function; after that all that needs to be done is to ensure that both expressions are using the same Parameter instance.
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);
}
The following code is used to replace all instances of an 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);
}
}
As for using the function; it's simple enough. We call Combine on your textExpression, and then we can create a lambda accepting both the row and the text result of the first expression as parameters. This lets you write a lambda that's almost exactly like the one you already have, but where you can use the text parameter to assign the Text value:
public IEnumerable<RowModel> GetRowModels(
Expression<Func<Row, string>> textExpr)
{
return MyDatabaseContext.MyTable.Select(
textExpr.Combine((row, text) => new RowModel
{
RowID = row.ID,
CreatedDate = row.CreatedDate,
AnotherProperty = row.AnotherProperty,
Text = text, // how do I bind this expression?
Value = row.OtherStuff.Where(os => os.ShouldUse)
.Select(os => os.Value).FirstOrDefault(),
AnotherValue = row.OtherStuff.Where(os => os.ShouldUseAgain)
.Select(os => os.Value).FirstOrDefault()
}));
}

Generic Linq to Entities filter method that accepts filter criteria and properties to be filtered

I've looked into many generic linq filtering questions and their answers here in SO but none of them satisfy my needs so I thought I should create a question.
I've created many of what I call "filter provider" classes, one for each entity class in my model, to provide a simplistic search for my application. I didn't want to go into more advanced solutions like Lucene.Net because a basic filtering with matching score would suffice.
Inside each one of these provider classes there are multiple methods that will receive the filtering terms and query specific properties, returning a score for each match based on the relevance of the property. Most methods will filter multiple properties at once, but not all.
Here are two of these methods:
private IQueryable<Retailer> MatchHighRelevanceFields(string searchTerm, IQueryable<Retailer> retailers)
{
var results = retailers.Where(r =>
(r.CompanyName != null && r.CompanyName.ToUpper().Contains(searchTerm))
|| (r.TradingName != null && r.TradingName.ToUpper().Contains(searchTerm))
);
return results;
}
private IQueryable<Retailer> MatchMediumRelevanceFields(string searchTerm, IQueryable<Retailer> retailers)
{
var results = retailers.Where(r =>
(r.Address.Street != null && r.Address.Street.ToUpper().Contains(searchTerm))
|| (r.Address.Complement != null && r.Address.Complement.ToUpper().Contains(searchTerm))
);
return results;
}
These methods are replicated ad nauseum throughout each provider class and I hope I could replace them for a single method that would receive the properties to be included in the query.
Something like:
public static IQueryable<T> Match<T>(string searchTerm, IQueryable<T> data, Expression<Func<T, string>> filterProperties)
{
var results = **build the query for each property in filterProperties**
return results;
}
But I really can't figure it out. I tried using reflection but it only worked with Linq to Objects and I need a solution for Linq to Entities.
So to solve this problem we need a few puzzle pieces first. The first puzzle piece is a method that can take an expression that computes a value, and then another expression that computes a new value taking the same type the first returns, and creates a new expression that represents the result of passing the result of the first function as the parameter to the second. This allows us to Compose expressions:
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 relies on the following tool 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);
}
}
We'll also need a tool to help us OR two predicate 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);
}
}
Now that we have this we can use Compose on each property selector to map it from the property results to whether or not that property value is non-null and contains the search term. We can then OR all of those predicates together to get a filter for your query:
public static IQueryable<T> Match<T>(
IQueryable<T> data,
string searchTerm,
IEnumerable<Expression<Func<T, string>>> filterProperties)
{
var predicates = filterProperties.Select(selector =>
selector.Compose(value =>
value != null && value.Contains(searchTerm)));
var filter = predicates.Aggregate(
PredicateBuilder.False<T>(),
(aggregate, next) => aggregate.Or(next));
return data.Where(filter);
}
You can do it with expression trees but it's not as simple as you might think.
public static IQueryable<T> Match<T>(this IQueryable<T> data, string searchTerm,
params Expression<Func<T, string>>[] filterProperties)
{
var parameter = Expression.Parameter(typeof (T), "source");
Expression body = null;
foreach (var prop in filterProperties)
{
// need to replace all the expressions with the one parameter (gist taken from Colin Meek blog see link on top of class)
//prop.body should be the member expression
var propValue =
prop.Body.ReplaceParameters(new Dictionary<ParameterExpression, ParameterExpression>()
{
{prop.Parameters[0], parameter}
});
// is null check
var isNull = Expression.NotEqual(propValue, Expression.Constant(null, typeof(string)));
// create a tuple so EF will parameterize the sql call
var searchTuple = Tuple.Create(searchTerm);
var matchTerm = Expression.Property(Expression.Constant(searchTuple), "Item1");
// call ToUpper
var toUpper = Expression.Call(propValue, "ToUpper", null);
// Call contains on the ToUpper
var contains = Expression.Call(toUpper, "Contains", null, matchTerm);
// And not null and contains
var and = Expression.AndAlso(isNull, contains);
// or in any additional properties
body = body == null ? and : Expression.OrElse(body, and);
}
if (body != null)
{
var where = Expression.Call(typeof (Queryable), "Where", new[] {typeof (T)}, data.Expression,
Expression.Lambda<Func<T, bool>>(body, parameter));
return data.Provider.CreateQuery<T>(where);
}
return data;
}
public static Expression ReplaceParameters(this Expression exp, IDictionary<ParameterExpression, ParameterExpression> map)
{
return new ParameterRebinder(map).Visit(exp);
}
Now you need to have a expressionvisitor to make all the expressions use one parameter
//http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx
public class ParameterRebinder : ExpressionVisitor
{
private readonly IDictionary<ParameterExpression, ParameterExpression> _map;
public ParameterRebinder(IDictionary<ParameterExpression, ParameterExpression> map)
{
_map = map;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (_map.ContainsKey(node))
{
return _map[node];
}
return base.VisitParameter(node);
}
}
Would use it like
var matches = retailers.Match("7", r => r.Address.Street, x => x.Address.Complement).ToList();
Warning - I checked this with linq to objects using the AsQueryable but didn't run it against EF.
You can use Linq.Dynamic to build the query.
public static IQueryable<T> Match<T>(
string searchTerm,
IQueryable<T> data,
params Expression<Func<T, string>>[] filterProperties) where T : class
{
var predicates = new List<string>();
foreach (var prop in filterProperties)
{
var lambda = prop.ToString();
var columnName = lambda.Substring(lambda.IndexOf('.') + 1);
var predicate = string.Format(
"({0} != null && {0}.ToUpper().Contains(#0))", columnName);
predicates.Add(predicate);
}
var filter = string.Join("||", predicates);
var results = data.Where(filter, searchTerm);
return results;
}
Usage.
var retailers = Match(
"asd", db.Retailers, r => r.CompanyName, r => r.TradingName);
var retailers = Match(
"asd", db.Retailers, r => r.Address.Street, r => r.Address.Complement);
Limitation.
The filter can only accept basic expression.
r => r.Name
r => r.PropA.Name
r => r.PropA.PropB.Name
Try to use Expressions like those all
http://www.codeproject.com/Articles/493917/Dynamic-Querying-with-LINQ-to-Entities-and-Express

c# expressions combine property expression with lambda expression

Please help to solve issue below:
public class TestParent
{
public int Number { get; set; }
}
public class Test
{
public TestParent Parent { get; set; }
}
class Program
{
static void Main(string[] args)
{
Expression<Func<TestParent, bool>> parentExpression = x => x.Number == 10;
Expression<Func<Test, TestParent>> testExpression = x => x.Parent;
var test = new Test {Parent = new TestParent {Number = 10}};
Expression<Func<Test, bool>> composedExpression = ?; // x => x.Parent.Number == 10
bool result = composedExpression.Compile()(test);
if (result)
{
Console.WriteLine("Test passed!");
}
}
}
We can create a Compose method for expressions like so:
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 using the following helper method to replace all instance 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);
}
}
This allows you to write:
Expression<Func<Test, bool>> composedExpression =
testExpression.Compose(parentExpression);
I think you are trying to create a new expression which consist of the logic which is now defined in the two separate expressions parentExpression and testExpression.
Unfortunately you cannot combine expressions like that easily (without breaking down the expressions and using the internal expression-bodies) because the parameters of the expressions are different, and you have to manually create the expression from the contents of the two expressions. You cannot use the two expressions as they are, and combine them.
You can compile the two expressions, and use them in a new expression. It would be something like this. But be warned, the composedExpression will be nothing more than an invoke of the compiled expressions. It will not contain the logic which is now defined in the other two expressions.
Expression<Func<TestParent, bool>> parentExpression = x => x.Number == 10;
Expression<Func<Test, TestParent>> testExpression = x => x.Parent;
var parentExpressionCompiled = parentExpression.Compile();
var testExpressionCompiled = testExpression.Compile();
var test = new Test {Parent = new TestParent {Number = 10}};
Expression<Func<Test, bool>> composedExpression = x => parentExpressionCompiled(testExpressionCompiled(x));
bool result = composedExpression.Compile()(test);
if (result) {
Console.WriteLine("Test passed!");
}
Get this done:
var composedExpression = testExpression.Combine(parentExpression, true);
where Combine implementation is from: Combining two lambda expressions in c#

Categories

Resources