(向底部回答)
我正在尝试建立一个结合
Func<T, bool>
委托给一个 ExpressionTree,它允许我传入一个值(在这种情况下为 badValue)并在谓词全部返回 true 并且考虑到二进制操作时得到一个布尔值。这是我第一次使用 Expression/ExpressionTrees,所以请温柔。
我收到此错误:
ArgumentException:无法调用“System.Boolean”类型的表达式
在这条线上:
collectAnswers = Expression.And(isEmpty.Body, Expression.Invoke(...
我已经以这种方式设置了该行,因为我需要value
在所有表达式之间共享对的引用(对吗?)。
我理想的情况是只有一堆
Expression<Func<blah, blah, bool>>
我可以将它们与逻辑运算符(And/Or/Not)一起传递到系统中,最后得到一个布尔值。希望允许动态构建值必须通过的规则。
在我要去的路上,这甚至可能吗?如果没有,我将不胜感激一些指导我走上正确道路的指针。
string badValue = "hello!";
const int minSize = 8;
const int maxSize = 30;
Expression<Func<string, bool>> stringLengthMax = value => value.Length < maxSize;
Expression<Func<string, bool>> stringLengthMin = value => value.Length > minSize;
Expression<Func<string, bool>> isEmpty = value => !string.IsNullOrEmpty(value);
BinaryExpression collectAnswers = Expression.And(stringLengthMax.Body, Expression.Invoke(stringLengthMin, stringLengthMax.Parameters));
collectAnswers = Expression.And(isEmpty.Body, Expression.Invoke(collectAnswers, stringLengthMax.Parameters));
Func<string, bool> shouldValidate = Expression.Lambda<Func<string, bool>>(collectAnswers, stringLengthMax.Parameters).Compile();
bool result = shouldValidate(badValue);
回答 我没有以正确的方式推动参数,下面是在放入 ExpressionTree 的多个表达式之间共享的多个参数的示例,并且单个布尔值来自已编译的 Func,isValid
const int minSize = 8;
const int maxSize = 30;
Expression<Func<string, int, bool>> stringLengthMax = (value, max) => value.Length <= max;
Expression<Func<string, int, bool>> stringLengthMin = (value, min) => value.Length >= min;
Expression<Func<string, bool>> isEmpty = value => string.IsNullOrEmpty(value);
ParameterExpression valueParameter = Expression.Parameter(typeof(string));
ParameterExpression minParameter = Expression.Parameter(typeof(int));
ParameterExpression maxParameter = Expression.Parameter(typeof(int));
Expression<Func<string, int, int, bool>> minMaxCheck =
Expression.Lambda<Func<string, int, int, bool>>(
Expression.And(Expression.Invoke(stringLengthMax, valueParameter, maxParameter),
Expression.Invoke(stringLengthMin, valueParameter, minParameter)), valueParameter, minParameter, maxParameter);
minMaxCheck = Expression.Lambda<Func<string, int, int, bool>>(
Expression.And(Expression.Invoke(minMaxCheck, valueParameter, minParameter, maxParameter),
Expression.Not(Expression.Invoke(isEmpty, valueParameter))), valueParameter, minParameter, maxParameter);
Func<string, int, int, bool> isValid = minMaxCheck.Compile();
bool resultFalse1 = isValid("hello!", minSize, maxSize); // false - too short
bool resultTrue1 = isValid("hello!", "hello!".Length, maxSize); // true - adjust min
bool resultFalse2 = isValid("1234567890123456789012345678901", minSize, maxSize); // false - too long
bool resultTrue2 = isValid("1234567890123456789012345678901", minSize, "1234567890123456789012345678901".Length); // true - adjust max
bool resultFalse3 = isValid(string.Empty, minSize, maxSize); // false - empty
bool shouldBeTrue = isValid("1234567890", minSize, maxSize); // true - just right
bool resultFalse4 = isValid("1234567890", maxSize, maxSize); // false - adjust min
bool resultFalse5 = isValid("1234567890", minSize, minSize); // false - adjust max