eval(string) to C# code

后端 未结 8 1946
傲寒
傲寒 2021-01-19 04:23

Is it possible to evaluate the following in C# at runtime

I have a class that contains 3 properties (Field,Operator,Value)

8条回答
  •  离开以前
    2021-01-19 05:01

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

提交回复
热议问题