这个方法 , 实际上就可以认为是这个 Expression 的工厂方法 。
[ Test]publicvoidExpression02( ){ varfilter = CreateFilter( 1, 5);varre = Enumerable.Range( 0, 10).AsQueryable.Where(filter).ToList; varexpectation = Enumerable.Range( 1, 4);re.Should.BeEquivalentTo(expectation); Expression<Func< int, bool>> CreateFilter( intminValue, intmaxValue) {returnx => x >= minValue && x < maxValue; }}
通过Func可以更加灵活的组合条件
那可以使用 minValue 和 maxValue 作为参数来制作工厂方法 , 那么用委托当然也可以 。
于是 , 我们可以把左边和右边分别定义成两个 Func , 从而由外部来决定左右具体的比较方式 。
[ Test] publicvoidExpression03( ) {varfilter = CreateFilter(x => x >= 1, x => x < 5); varre = Enumerable.Range( 0, 10).AsQueryable .Where(filter).ToList;varexpectation = Enumerable.Range( 1, 4); re.Should.BeEquivalentTo(expectation);Expression<Func< int, bool>> CreateFilter(Func< int, bool> leftFunc, Func< int, bool> rightFunc) {returnx => leftFunc.Invoke(x) && rightFunc.Invoke(x); }}
也可以手动构建表达式
实际上 , 左右两个不仅仅是两个Func , 其实也可以直接是两个表达式 。
不过稍微有点不同的是 , 表达式的合并需要用 Expression 类型中的相关方法创建 。
我们可以发现 , 调用的地方这次其实没有任何改变 , 因为 Lambda 既可以隐式转换为 Func 也可以隐式转换为 Expression 。
每个方法的意思可以从注释中看出 。
[ Test] publicvoidExpression04( ) {varfilter = CreateFilter(x => x >= 1, x => x < 5); varre = Enumerable.Range( 0, 10).AsQueryable .Where(filter).ToList;varexpectation = Enumerable.Range( 1, 4); re.Should.BeEquivalentTo(expectation);Expression<Func< int, bool>> CreateFilter(Expression<Func< int, bool>> leftFunc, Expression<Func< int, bool>> rightFunc) {// xvarpExp = Expression.Parameter( typeof( int), "x"); // (a => leftFunc(a))(x)varleftExp = Expression.Invoke(leftFunc, pExp); // (a => rightFunc(a))(x)varrightExp = Expression.Invoke(rightFunc, pExp); // (a => leftFunc(a))(x) && (a => rightFunc(a))(x)varbodyExp = Expression.AndAlso(leftExp, rightExp); // x => (a => leftFunc(a))(x) && (a => rightFunc(a))(x)varresultExp = Expression.Lambda<Func< int, bool>>(bodyExp, pExp); returnresultExp; }}
推荐阅读