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
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
.
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>
?