Created
February 21, 2024 08:57
-
-
Save holyqqwqqasd/80f92ef23f7ef4d2518eb6fa3845a589 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ExpressionLogicalOperators | |
{ | |
public static Expression<Func<T, bool>> And<T>( | |
Expression<Func<T, bool>> expr1, | |
Expression<Func<T, bool>> expr2) | |
{ | |
var parameter = Expression.Parameter(typeof(T), expr1.Parameters[0].Name); | |
var left = ExpressionHelper.ReplaceParameter(expr1.Body, expr1.Parameters[0], parameter); | |
var right = ExpressionHelper.ReplaceParameter(expr2.Body, expr2.Parameters[0], parameter); | |
var body = Expression.AndAlso(left, right); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
public static Expression<Func<T, bool>> Or<T>( | |
Expression<Func<T, bool>> expr1, | |
Expression<Func<T, bool>> expr2) | |
{ | |
var parameter = Expression.Parameter(typeof(T), expr1.Parameters[0].Name); | |
var left = ExpressionHelper.ReplaceParameter(expr1.Body, expr1.Parameters[0], parameter); | |
var right = ExpressionHelper.ReplaceParameter(expr2.Body, expr2.Parameters[0], parameter); | |
var body = Expression.OrElse(left, right); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
public static Expression<Func<T, bool>> Not<T>(Expression<Func<T, bool>> expr) | |
{ | |
var parameter = Expression.Parameter(typeof(T), expr.Parameters[0].Name); | |
var body = Expression.Not(ExpressionHelper.ReplaceParameter(expr.Body, expr.Parameters[0], parameter)); | |
return Expression.Lambda<Func<T, bool>>(body, parameter); | |
} | |
} | |
public static class ExpressionCompose | |
{ | |
/// <summary> | |
/// Converts (f : A => B, g : B => C) into (A => C), inlining f body into g | |
/// </summary> | |
public static Expression<Func<TSource, TResult>> Compose<TSource, TIntermediate, TResult>( | |
Expression<Func<TSource, TIntermediate>> first, | |
Expression<Func<TIntermediate, TResult>> second) | |
{ | |
var param = Expression.Parameter(typeof(TSource), first.Parameters[0].Name); | |
var intermediateValue = ExpressionHelper.ReplaceParameter(first.Body, first.Parameters[0], param); | |
var body = ExpressionHelper.ReplaceParameter(second.Body, second.Parameters[0], intermediateValue); | |
return Expression.Lambda<Func<TSource, TResult>>(body, param); | |
} | |
} | |
internal static class ExpressionHelper | |
{ | |
public static Expression ReplaceParameter( | |
Expression expression, | |
ParameterExpression toReplace, | |
Expression newExpression) | |
=> new ParameterReplaceVisitor(toReplace, newExpression).Visit(expression) ?? expression; | |
} | |
internal sealed class ParameterReplaceVisitor : ExpressionVisitor | |
{ | |
private readonly ParameterExpression _from; | |
private readonly Expression _to; | |
public ParameterReplaceVisitor(ParameterExpression from, Expression to) | |
{ | |
_from = from; | |
_to = to; | |
} | |
protected override Expression VisitParameter(ParameterExpression node) => | |
node == _from ? _to : node; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment