using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace APT.Infrastructure.Core
{
///
/// Expression表达式扩展操作类
///
public static class ExpressionExtensions
{
///
/// 以特定的条件运行组合两个Expression表达式
///
/// 表达式的主实体类型
/// 第一个Expression表达式
/// 要组合的Expression表达式
/// 组合条件运算方式
/// 组合后的表达式
public static Expression Compose(this Expression first, Expression second, Func merge)
{
Dictionary map =
first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
Expression secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
return Expression.Lambda(merge(first.Body, secondBody), first.Parameters);
}
///
/// 以 Expression.AndAlso 组合两个Expression表达式
///
/// 表达式的主实体类型
/// 第一个Expression表达式
/// 要组合的Expression表达式
/// 组合后的表达式
public static Expression> And(this Expression> first, Expression> second)
{
return first.Compose(second, Expression.AndAlso);
}
///
/// 以 Expression.OrElse 组合两个Expression表达式
///
/// 表达式的主实体类型
/// 第一个Expression表达式
/// 要组合的Expression表达式
/// 组合后的表达式
public static Expression> Or(this Expression> first, Expression> second)
{
return first.Compose(second, Expression.OrElse);
}
private class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary _map;
private ParameterRebinder(Dictionary map)
{
_map = map ?? new Dictionary();
}
public static Expression ReplaceParameters(Dictionary map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression node)
{
ParameterExpression replacement;
if (_map.TryGetValue(node, out replacement))
{
node = replacement;
}
return base.VisitParameter(node);
}
}
}
}