Parse boolean condition into expression tree

c# expression-trees linq

Question

If I have a method that takes a boolean like:

public void Foo(boolean condition)

And call it like this:

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

Can I compose that into an expression tree in order to construct a query to some other datasource that will use MyField as one parameter and MyValue and another. I can only seem to make that condition into a expression that evaluates to false.

UPDATE

    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);

Where Field is a class with two properties, Name and Value

Accepted Answer

Foo("MyField" == "MyValue") is, as noted at the bottom of the question, a constant false (right up at the compiler). You have a few choices here - the simplest of course is to do something like:

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

and call with

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

then here, there is nothing left to do; we already have the expression. So I assume you mean "MyField" is a string only known at runtime, in which case:

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);
}

and call with Foo("MyField", "MyValue) (with an implicit <string> in there, courtesy of the compiler), or Foo("MyField", 123) if the prop is an int (implicit <int>),

The final scenario is where "MyValue" is also a string only known at runtime (emph: string) - in which case we'll need to parse it:

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);
}

Here the call is always 2 strings - so Foo("MyField", "123") even when int.


Popular Answer

In can create expression trees from delegates. For example, if you define your method so that it takes a delegate as a parameter, you can use it as follows:

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

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

In order to create an expression tree, rather than execute the delegate, change the method as follows:

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

However, in your case, you will find that your expression is a boolean constant with a value of 'false', this is because the compiler has evaluated "MyField" == "MyValue" which is of course false.

If you just want name-value pairs, which not just use a Dictionary<string, string> ?




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why