c# – 如何评估ExpressionVisitor中的表达式?
发布时间:2020-12-16 01:50:28 所属栏目:百科 来源:网络整理
导读:我需要在执行它之前使用ExpressionVisitor来分析Expression.根据我的需要,我需要评估Divide表达式的正确部分,但我不知道该怎么做.这是我的示例代码: internal class RulesChecker : ExpressionVisitor{ private readonly object data; public RulesChecker(
我需要在执行它之前使用ExpressionVisitor来分析Expression.根据我的需要,我需要评估Divide表达式的正确部分,但我不知道该怎么做.这是我的示例代码:
internal class RulesChecker : ExpressionVisitor { private readonly object data; public RulesChecker(object data) { this.data = data; } protected override Expression VisitBinary(BinaryExpression node) { if (node.NodeType == ExpressionType.Divide) { var rightExpression = node.Right; // compile the right expression and get his value } return base.VisitBinary(node); } } 假设我有这个代码来评估: Expression<Func<DataInfo,decimal?>> expression = x => x.A / (x.B + x.C); var rulesChecker = new RulesChecker(data); rulesChecker.Visit(expression); 在VisitBinary函数中,我将收到一个节点,该节点将包含除法运算的左右部分.我的问题是,我如何评估我将在操作的正确部分获得的价值? 解决方法
我认为这个问题最困难的部分是处理变量.所以我首先要替换常量变量.之后,您只需执行并更新Expression.
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace WindowsFormsApplication1 { static class Program { [STAThread] static void Main() { var value1 = 1; var value2 = 2; var value3 = new { MyValue = 3 }; var data = new DataInfo { A = 10,B = 1,C = -1 }; Expression<Func<DataInfo,decimal?>> expression = x => x.A / (x.B + x.C) + (value1 + value2) + value3.MyValue; // create a list of variables that will be used when evaluating the expression var variables = new Dictionary<Type,object>(); // add the root object variables.Add(data.GetType(),data); // find variables that are referenced in the expression var finder = new VariablesFinder(variables); finder.Visit(expression); // replace variables with ConstantExpressions var visitor = new VariableReplacer(variables); var newExpression = visitor.Visit(expression); var rulesChecker = new RulesChecker(); var checkedExpression = rulesChecker.Visit(newExpression); } } internal class RulesChecker : ExpressionVisitor { protected override Expression VisitBinary(BinaryExpression node) { if (node.NodeType == ExpressionType.Divide) { var rightBinaryExpression = node.Right as BinaryExpression; if (rightBinaryExpression != null) { node = node.Update(node.Left,node.Conversion,this.Execute(rightBinaryExpression)); } } return base.VisitBinary(node); } private Expression Execute(BinaryExpression node) { var lambda = Expression.Lambda(node); dynamic func = lambda.Compile(); var result = func(); return Expression.Constant(result,result.GetType()); } } internal class VariableReplacer : ExpressionVisitor { private readonly Dictionary<Type,object> _variables; public VariableReplacer(Dictionary<Type,object> variables) { this._variables = variables; } protected override Expression VisitMember(MemberExpression node) { return this.HandleProperty(node) ?? this.HandleField(node) ?? node; } private Expression HandleField(MemberExpression memberExpression) { var fieldInfo = memberExpression.Member as FieldInfo; if (fieldInfo != null) { var value = fieldInfo.GetValue(this.GetVarialbe(fieldInfo)); return Expression.Constant(value,fieldInfo.FieldType); } return null; } private Expression HandleProperty(MemberExpression memberExpression) { var propertyInfo = memberExpression.Member as PropertyInfo; if (propertyInfo != null) { var value = propertyInfo.GetValue(this.GetVarialbe(propertyInfo),null); return Expression.Constant(value,propertyInfo.PropertyType); } return null; } private object GetVarialbe(MemberInfo memberInfo) { return this._variables[memberInfo.DeclaringType]; } } internal class VariablesFinder : ExpressionVisitor { private readonly Dictionary<Type,object> _variables; public VariablesFinder(Dictionary<Type,object> variables) { this._variables = variables; } protected override Expression VisitConstant(ConstantExpression node) { this.AddVariable(node.Type,node.Value); return base.VisitConstant(node); } private void AddVariable(Type type,object value) { if (type.IsPrimitive) { return; } if (this._variables.Keys.Contains(type)) { return; } this._variables.Add(type,value); var fields = type.GetFields().Where(x => !x.FieldType.IsPrimitive).ToList(); foreach (var field in fields) { this.AddVariable(field.FieldType,field.GetValue(value)); } } } class DataInfo { public int A { get; set; } public int B { get; set; } public int C { get; set; } public int D; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |