Is it possible to evaluate the following in C# at runtime
I have a class that contains 3 properties (Field
,Operator
,Value
)
You'd have to either use the CodeDOM libraries or create an Expression tree, compile it, and execute it. I think building up the expression tree is the best option.
Of course you could put in a switch statement on your operator, which is not bad because there is a limited number of operators you could use anyways.
Here's a way to do this with expression trees (written in LINQPad):
void Main()
{
var programmers = new List{
new Programmer { Name = "Turing", Number = Math.E},
new Programmer { Name = "Babbage", Number = Math.PI},
new Programmer { Name = "Lovelace", Number = Math.E}};
var rule0 = new Rule() { Field = "Name", Operator = BinaryExpression.Equal, Value = "Turing" };
var rule1 = new Rule() { Field = "Number", Operator = BinaryExpression.GreaterThan, Value = 2.719 };
var matched0 = RunRule(programmers, rule0);
matched0.Dump();
var matched1 = RunRule(programmers, rule1);
matched1.Dump();
var matchedBoth = matched0.Intersect(matched1);
matchedBoth.Dump();
var matchedEither = matched0.Union(matched1);
matchedEither.Dump();
}
public IEnumerable RunRule(IEnumerable foos, Rule rule) {
var fieldParam = Expression.Parameter(typeof(T), "f");
var fieldProp = Expression.Property (fieldParam, rule.Field);
var valueParam = Expression.Parameter(typeof(V), "v");
BinaryExpression binaryExpr = rule.Operator(fieldProp, valueParam);
var lambda = Expression.Lambda>(binaryExpr, fieldParam, valueParam);
var func = lambda.Compile();
foreach(var foo in foos) {
var result = func(foo, rule.Value);
if(result)
yield return foo;
}
}
public class Rule {
public string Field { get; set; }
public Func Operator { get; set; }
public T Value { get; set; }
}
public class Programmer {
public string Name { get; set; }
public double Number { get; set; }
}