Skip to content

Instantly share code, notes, and snippets.

@aetos382
Last active February 9, 2018 09:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aetos382/e5529fc5c9f32302adfb to your computer and use it in GitHub Desktop.
Save aetos382/e5529fc5c9f32302adfb to your computer and use it in GitHub Desktop.
public static class ExpressionCombiner
{
public static Expression<Func<T, bool>> OrElse<T>(
params Expression<Func<T, bool>>[] expressions)
{
return OrElse(expressions.AsEnumerable());
}
public static Expression<Func<T, bool>> OrElse<T>(
this IEnumerable<Expression<Func<T, bool>>> expressions)
{
if (!expressions.Any())
{
throw new ArgumentException($"parameter [{nameof(expressions)}] is empty.", nameof(expressions));
}
var lambda = expressions.First();
var body = lambda.Body;
var parameter = lambda.Parameters[0];
foreach (var expression in expressions.Skip(1))
{
var visitor = new ParameterReplaceVisitor(expression.Parameters[0], parameter);
body = Expression.OrElse(body, visitor.Visit(expression.Body));
}
lambda = Expression.Lambda<Func<T, bool>>(body, parameter);
return lambda;
}
}
internal class ParameterReplaceVisitor :
ExpressionVisitor
{
private readonly ParameterExpression _originalParameter;
private readonly ParameterExpression _newParameter;
public ParameterReplaceVisitor(
ParameterExpression originalParameter,
ParameterExpression newParameter)
{
this._originalParameter = originalParameter;
this._newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == this._originalParameter)
{
return this._newParameter;
}
return base.VisitParameter(node);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment