public static Expression <Func <T, bool> > ToExpression <T>(this AxiomFilter filter) { var axDict = GetAxiomExpressionDictionary <T>(filter); filter.Format = filter.Format.Replace(AND_ALSO, AND).Replace(OR_ELSE, OR); var junctionDict = new Dictionary <string, Func <Expression <Func <T, bool> >, Expression <Func <T, bool> >, Expression <Func <T, bool> > > >() { { AND, TypeExtensions.AndAlso }, { OR, TypeExtensions.OrElse } }; Func <string, bool> IsBinOperator = (string s) => { return(s == AND || s == OR); }; Func <string, bool> IsUnaryOperator = (string s) => { return(s == NOT); }; Func <object, Expression <Func <T, bool> > > GetAxiomFunc = (object o) => { if (!(o is Token)) { return(o as Expression <Func <T, bool> >); } return(axDict[((Token)o).Value]); }; using (var reader = new StringReader(filter.Format)) { var parser = new Parser(); var tokens = parser.Tokenize(reader).ToList(); var rpn = parser.ShuntingYard(tokens).ToList(); var processStack = new Stack <object>(); var i = 0; do { var t = rpn[i]; if (IsBinOperator(t.Value)) { processStack.Push( junctionDict[t.Value]( GetAxiomFunc(processStack.Pop()), GetAxiomFunc(processStack.Pop()) ) ); } else if (IsUnaryOperator(t.Value)) { processStack.Push( TypeExtensions.Not( GetAxiomFunc(processStack.Pop()) ) ); } else { processStack.Push(t); } i++; }while (i < rpn.Count); var exp = processStack.Pop() as Expression <Func <T, bool> >; return((exp.CanReduce) ? exp.Reduce() as Expression <Func <T, bool> > : exp); } }
private static Dictionary <string, Expression <Func <T, bool> > > GetAxiomExpressionDictionary <T>(AxiomFilter filter) { var type = typeof(T); var axiomDict = new Dictionary <string, Expression <Func <T, bool> > >(); var paramExpression = Expression.Parameter(type, "🖕🏽"); foreach (var a in filter.Axioms) { var conditionalExpression = a.ToExpression <T>(paramExpression); axiomDict.Add($"{{{a.Key}}}", conditionalExpression); } return(axiomDict); }