我正在创建一个名为
以下测试代码展示了我的意图。
我看到了以下问题:如何组合现有的Linq表达式,它向我展示了如何使用
例如,我有以下两个表达式:
我希望创建一个类似于这样的新表达式:
更简洁地说,我正在尝试创建以下功能:
Validator<T>
的类。我试图实现Linq SelectMany
扩展方法,以便我的验证器能够使用Linq查询组合表达式,并在基础值更改时验证最终结果。以下测试代码展示了我的意图。
var a = 2;
var b = 3;
var va = Validator.Create(() => a, n => n >= 0 && n < 5);
var vb = Validator.Create(() => b, n => n >= 0 && n < 5);
var vc = from ia in va
from ib in vb
select ia + ib;
Debug.Assert(vc.Value == a + b); //2 + 3
Debug.Assert(vc.Value == 5);
Debug.Assert(vc.IsValid == true);
a = 7;
Debug.Assert(vc.Value == a + b); //7 + 3
Debug.Assert(vc.Value == 10);
Debug.Assert(va.IsValid == false);
Debug.Assert(vb.IsValid == true);
Debug.Assert(vc.IsValid == false);
我看到了以下问题:如何组合现有的Linq表达式,它向我展示了如何使用
And
表达式将两个Func<T, bool>
组合在一起,但我需要以更加函数化的方式将函数组合在一起。例如,我有以下两个表达式:
public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }
我希望创建一个类似于这样的新表达式:
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions rather than compile & invoke.
}
}
更简洁地说,我正在尝试创建以下功能:
// Specific case
Func<Expression<Func<T>>, Expression<Func<T, bool>>, Expression<Func<bool>>>
// General case
Func<Expression<Func<X, Y>>, Expression<Func<Y, Z>>, Expression<Func<X, Z>>>
通用情况下,函数可以被修改以接受所需的不同数量的通用参数,以组成任何函数。
我已经在Stack Overflow(当然)和网络上搜索过,但没有找到解决这个问题的示例。
Validator<T>
类的代码如下。
public class Validator<T>
{
public Validator(Expression<Func<T>> valueFunc,
Expression<Func<T, bool>> validationFunc)
{
this.ValueExpression = valueFunc;
this.ValidationExpression = validationFunc;
}
public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }
public T Value { get { return this.ValueExpression.Compile().Invoke(); } }
public bool IsValid { get { return this.IsValidExpression.Compile().Invoke(); } }
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions.
}
}
}
我的SelectMany
扩展包含大量令人讨厌的.Compile().Invoke()
,我想摆脱它们。
public static Validator<U> SelectMany<T, U>(this Validator<T> @this, Expression<Func<T, Validator<U>>> k)
{
Expression<Func<T>> fvtv = @this.ValueExpression;
Expression<Func<Validator<U>>> fvu = () => k.Compile().Invoke(fvtv.Compile().Invoke());
Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
Expression<Func<U, bool>> fvtiv = u => @this.ValidationExpression.Compile().Invoke(fvtv.Compile().Invoke());
return fvuv.ToValidator(fvtiv);
}
public static Validator<V> SelectMany<T, U, V>(this Validator<T> @this, Expression<Func<T, Validator<U>>> k, Expression<Func<T, U, V>> s)
{
Expression<Func<Validator<U>>> fvu = () => @this.SelectMany(k);
Expression<Func<T>> fvtv = @this.ValueExpression;
Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
Expression<Func<T, bool>> fvtiv = @this.ValidationExpression;
Expression<Func<U, bool>> fvuiv = u => fvu.Compile().Invoke().ValidationExpression.Compile().Invoke(u);
Expression<Func<V>> fvv = () => s.Compile().Invoke(fvtv.Compile().Invoke(), fvuv.Compile().Invoke());
Expression<Func<V, bool>> fvviv = v => fvtiv.Compile().Invoke(fvtv.Compile().Invoke()) && fvuiv.Compile().Invoke(fvuv.Compile().Invoke());
return fvv.ToValidator(fvviv);
}
提前感谢您!