Reputation: 1165
I faced a little bit problem with Expression<>
.
Is it possible to combine more than 2 expression in to one? Example:
Expression<Func<Event, bool>> searchForLogCorrelationKeyExpression =
x => string.Equals(x.LOG_CORR_KEY, model.CorrelationKey, StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLsidExpressionExpression =
x => string.Equals(x.LOG_LSID, model.LsId, StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLogLocationExpression =
x => string.Equals(x.LOG_LOCATION, model.LogLocation, StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLogTypeExpression =
x => string.Equals(x.LOG_TP, model.LogType.ToString(), StringComparison.CurrentCultureIgnoreCase);
if (model.EndDateTime != null && model.StartDateTime != null)
{
Expression<Func<Event, bool>> searchForLogInDateRangeExpression =
x => model.StartDateTime <= x.LOG_TS && model.EndDateTime <= x.LOG_TS;
}
Expression<Func<Event, bool>> searchForLogByUserIdExpression =
x => string.Equals(x.LOG_USERID, model.UserId.ToString(), StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLogByLogTextExpression =
x => string.Equals(x.LOG_TXT, model.SearchString.ToString(), StringComparison.CurrentCultureIgnoreCase);
I have 7 expressions that I want to combine in to one and then put it to the method that accepts Expression<Func<Event, bool>>
as a parameter.
Is it possible? I found many example with combining two expressions but they didn't work.
Upvotes: 0
Views: 103
Reputation: 6222
Fiddle: https://dotnetfiddle.net/V7Ol0J
Source of knowledge: https://www.codeproject.com/Articles/895951/Combining-expressions-to-dynamically-append-criter
Here is a working example:
public class Event
{
public string A {get;set;}
public string B {get;set;}
public string C {get;set;}
}
public static class Extensions
{
public static Expression<Func<T, Boolean>> AndAlso<T>(this Expression<Func<T, Boolean>> left, Expression<Func<T, Boolean>> right)
{
Expression<Func<T, Boolean>> combined = Expression.Lambda<Func<T, Boolean>>(
Expression.AndAlso(
left.Body,
new ExpressionParameterReplacer(right.Parameters, left.Parameters).Visit(right.Body)
), left.Parameters);
return combined;
}
}
public class ExpressionParameterReplacer : ExpressionVisitor
{
private IDictionary<ParameterExpression, ParameterExpression> ParameterReplacements { get; set; }
public ExpressionParameterReplacer(IList<ParameterExpression> fromParameters, IList<ParameterExpression> toParameters)
{
ParameterReplacements = new Dictionary<ParameterExpression, ParameterExpression>();
for(int i = 0; i != fromParameters.Count && i != toParameters.Count; i++)
{ ParameterReplacements.Add(fromParameters[i], toParameters[i]); }
}
protected override Expression VisitParameter(ParameterExpression node)
{
ParameterExpression replacement;
if(ParameterReplacements.TryGetValue(node, out replacement))
{ node = replacement; }
return base.VisitParameter(node);
}
}
Usage:
Expression<Func<Event, bool>> searchForLogCorrelationKeyExpression = x => string.Equals(x.A, "A", StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLsidExpressionExpression = x => string.Equals(x.B, "B", StringComparison.CurrentCultureIgnoreCase);
Expression<Func<Event, bool>> searchForLogLocationExpression = x => string.Equals(x.C, "C", StringComparison.CurrentCultureIgnoreCase);
var res = searchForLogCorrelationKeyExpression.AndAlso(searchForLsidExpressionExpression).AndAlso(searchForLogLocationExpression);
Console.WriteLine(res.Compile()(new Event(){A="A",B="B",C="C"}));
Upvotes: 1