否定表达式

Negating an Expression

我有一个函数 return 是一个表达式,我传入一个字段和一个值。我有函数 returning StartsWith,但我想 return 而不是 StartsWith

private Expression<Func<T, bool>> GenerateFieldDoesNotStartsWithExpression<T>(string fieldName, string value) {
    var parameter = Expression.Parameter(typeof(T), "i");
    var fieldAccess = Expression.PropertyOrField(parameter, fieldName);
    MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    var passedValue = Expression.Constant(value, typeof(string));
    var body = Expression.Call(fieldAccess, method, passedValue);
    var expr = Expression.Lambda<Func<T, bool>>(body, parameter);
    return expr;
}

Returns i.[fieldName].StartsWith(value) 但我正在寻找 !i.[fieldName].StartsWith(value).

我尝试了一些操作,例如将 parameter = !i 和第二个参数设置为 i,但后来我得到 "parameter '!i' was not bound".

我试过 Expression.Not,但似乎无法正常工作。

Expression.Not

包围你Expression.Call
var body = Expression.Not(Expression.Call(fieldAccess, method, passedValue));

您的代码:

    private Expression<Func<T, bool>> GenerateFieldDoesNotStartsWithExpression<T>(string fieldName, string value)
    {
        var parameter = Expression.Parameter(typeof(T), "i");
        var fieldAccess = Expression.PropertyOrField(parameter, fieldName);
        MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
        var passedValue = Expression.Constant(value, typeof(string));
        // Wrapped Expression.Call with Expression.Not
        var body = Expression.Not(Expression.Call(fieldAccess, method, passedValue));
        var expr = Expression.Lambda<Func<T, bool>>(body, parameter);
        return expr;
    }

测试代码:

[TestFixture]
public class ExpressNotTests
{
    [Test]
    public void GenerateFieldDoesNotStartsWithExpression_DoesNotStartWith_True()
    {
        var a = new TestClass() {TestString = "Not"};

        var exp = GenerateFieldDoesNotStartsWithExpression<TestClass>("TestString", "Test");

        var res = exp.Compile()(a);

        res.Should().BeTrue();
    }

    [Test]
    public void GenerateFieldDoesNotStartsWithExpression_DoesStartsWith_False()
    {
        var a = new TestClass() {TestString = "TestString"};

        var exp = GenerateFieldDoesNotStartsWithExpression<TestClass>("TestString", "Test");

        var res = exp.Compile()(a);

        res.Should().BeFalse();
    }


    private class TestClass
    {
        public string TestString { get; set; }
    }
}