将布尔条件解析为表达式树

时间:2011-02-01 08:31:12

标签: c# linq expression-trees

如果我有一个采用布尔值的方法:

public void Foo(boolean condition)

并称之为:

Foo("MyField" == "MyValue");

我可以将它组成一个表达式树,以便构建一个查询到一些其他数据源,该数据源将MyField用作一个参数,MyValue和另一个。 我似乎只能将这个条件变成一个计算结果为false的表达式。

更新

    var param = Expression.Parameter(typeof(Field), field);
    var prop = Expression.PropertyOrField(param, "Name");

    ConstantExpression @const = Expression.Constant(value, typeof(string));
    var body = Expression.Equal(prop, @const);
    var lambda = Expression.Lambda<Func<Field, bool>>(body, param);

其中Field是一个具有两个属性的类,名称和值

2 个答案:

答案 0 :(得分:4)

正如问题底部所指出的,

Foo("MyField" == "MyValue")是一个常量false(编译器正确)。你有几个选择 - 最简单的当然是做一些事情:

void Foo(Expression<Func<YourType,bool>> predicate) {...}

并致电

Foo(x => x.MyField == "MyValue");

然后这里,没有什么可做的;我们已经有了表达方式。所以我假设你的意思是“MyField”是一个只在运行时知道的字符串,在这种情况下:

void Foo<T>(string fieldName, T value) {
   var param = Expression.Parameter(typeof(YourType), "x");
   var body = Expression.Equal(
                  Expression.PropertyOrField(param, fieldName),
                  Expression.Constant(value, typeof(T))
               );
   var lambda = Expression.Lambda<Func<YourType, bool>>(body, param);
}

并使用Foo("MyField", "MyValue)进行调用(由编译器提供隐式<string>)或Foo("MyField", 123)如果prop是int(隐式{{1} }}),

最后一个场景是<int>也是字符串,仅在运行时已知(emph:"MyValue") - 在这种情况下,我们需要解析它:< / p>

string

此处的通话总是2个字符串 - 所以void Foo(string fieldName, string value) { var param = Expression.Parameter(typeof(YourType), "x"); var prop = Expression.PropertyOrField(param, fieldName); ConstantExpression @const; if(prop.Type == typeof(string)) { @const = Expression.Constant(value, typeof(string)); } else { object parsed = TypeDescriptor.GetConverter(prop.Type) .ConvertFromInvariantString(value); @const = Expression.Constant(parsed, prop.Type); } var body = Expression.Equal(prop,@const); var lambda = Expression.Lambda<Func<YourType, bool>>(body, param); } 即使Foo("MyField", "123")

答案 1 :(得分:1)

In可以从委托创建表达式树。例如,如果您定义方法以便将委托作为参数,则可以按如下方式使用它:

public void Foo(Func<bool> fn)
{
    // invoke the passed delegate
    var result = fn();
}

Foo(() => "MyField" == "MyValue");

为了创建表达式树而不是执行委托,请按如下方式更改方法:

public void Foo(Expression<Func<bool>> expression)
{
   // inspect your expression tree here
}

但是,在你的情况下,你会发现你的表达式是一个值为'false'的布尔常量,这是因为编译器已经评估了"MyField" == "MyValue",这当然是假的。

如果您只想要名称 - 值对,而不只是使用Dictionary<string, string>