C# 计算复杂表达式树

C# 计算复杂表达式树,c#,expression-trees,C#,Expression Trees,我有一个基本的规则引擎,我以一种与这里建议的路线非常相似的方式构建了它: 我根据进一步的需求扩展了它,现在我需要评估复杂的类,例如 EvaluateRule("Transaction.IsOpen", "Equals", "true") 代码最基本的形式是: var param = inputMessageType; left = Expression.Property(param, memberName); tProp = typeof(T).GetProperty(r.MemberN

我有一个基本的规则引擎,我以一种与这里建议的路线非常相似的方式构建了它:

我根据进一步的需求扩展了它,现在我需要评估复杂的类,例如

EvaluateRule("Transaction.IsOpen", "Equals", "true")  
代码最基本的形式是:

var param = inputMessageType;
left = Expression.Property(param, memberName);
tProp = typeof(T).GetProperty(r.MemberName).PropertyType;
right = Expression.Constant(Convert.ChangeType(r.TargetValue, tProp));
return Expression.MakeBinary(tBinary, left, right);    
为了评估复杂的类,我使用了类似于以下的方法:

我遇到的问题是,当我尝试使用类的属性(Transaction.IsOpen)计算规则时,我得到的是表达式右侧的根类型,但表达式左侧的复杂对象类型

这将导致以下错误:

System.InvalidOperationException: The binary operator Equal is not defined for the types 'System.Func`2[Transaction,System.Boolean]' and 'System.Boolean'.
我如何克服这个问题?我不是使用表达式树的专家,当示例偏离标准文档时,许多概念都很难理解

编辑:这是代码(我省略了一些特定于环境的内容,以便关注问题)

public Actions EvaluateRulesFromMessage(clientEventQueMessage消息)
{            
var ruleGroups=_ruleRepository.GetRuleList();
var actions=新操作();
foreach(规则组中的变量规则组)
{
如果(message.MessageType==“UI\U更新”)
{
//清理json对象
JObject-dsPayload=(JObject.Parse(message.Payload));
var msgParams=JsonConvert.DeserializeObject(message.Payload);
msgParams.RulesCompleted=msgParams.RulesCompleted??新列表();
var conditionsMet=false;
//处理规则,筛选出已评估的规则
var filteredRules=ruleGroup.Rules.Where(项=>
!msgParams.RulesCompleted.Any(r=>r.Equals(item.Id));
foreach(filteredRules中的var规则)
{                        
Func compiledRule=CompileRule(规则,msgParams);
if(编译规则(msgParams))
{
conditionsMet=true;
}
其他的
{
conditionsMet=false;
打破
}                        
}
if(conditionsMet)
{                        
actions=AddAction(消息、规则组);
打破
}
}
}                
返回动作;
}
公共函数编译器(规则r,UiTransactionUpdate消息)
{
var expression=expression.Parameter(typeof(UiTransactionUpdate));
表达式expr=BuildExpr(r,表达式,msg);
//构建lambda函数UiTransactionUpdate->bool并编译它
返回表达式.Lambda(expr,Expression.Compile();
}
静态表达式求值(对象根、字符串属性字符串、输出类型tProp)
{
Type=null;
var propertyNames=propertyString.Split('.');
ParameterExpression param=Expression.Parameter(root.GetType());
表达式属性=参数;
字符串propName=“”;
foreach(propertyNames中的var属性)
{                           
property=MemberExpression.PropertyOrField(属性,属性);
type=property.type;
propName=prop;
}
tProp=Type.GetType(Type.underyingSystemType.AssemblyQualifiedName);
var param2=MemberExpression.Parameter(tProp);
var e=表达式.Lambda(属性,参数);
返回e;
}
静态表达式BuildExpr(规则r、参数Expression param、UiTransactionUpdate消息)
{
表情左;
tProp型;
字符串memberName=r.memberName;
if(memberName.Contains(“.”)
{
左=Eval(msg、memberName、out tProp);
}
其他的
{
left=Expression.Property(param,memberName);
tProp=typeof(T).GetProperty(r.MemberName).PropertyType;
}
表达型tBinary;
if(ExpressionType.TryParse(r.运算符,out-tBinary))
{
表达式right=null;
switch(r.ValueType)///todo:需要将其重构为独立于类型的
{
案例TargetValueType。值:
右=表达式.Constant(Convert.ChangeType(r.TargetValue,tProp));
打破
}
//使用二进制操作,即true/false
返回表达式.MakeBinary(tBinary、left、right);
}
其他的
{
var method=tProp.GetMethod(r.Operator);
var tParam=method.GetParameters()[0].ParameterType;
var right=表达式常数(Convert.ChangeType(r.TargetValue,tParam));
//使用方法调用,例如“Contains”->“u.Tags.Contains(some_tag)”
返回表达式.Call(左、方法、右);
}
}

示例代码没有涵盖场景中使用的所有数据类型,因此很难准确判断它在何处中断,但从异常
System.Func'2[Transaction,System.Boolean]和'System.Boolean
可以看出,在左手边有一个接受
Transaction
并返回
bool的委托(
Func
),右手边就是
bool

无法将
Func
bool
进行比较,但可以调用函数并比较其结果:

Func<Transaction, bool> func = ...;
bool comparand = ...;
Transaction transaction = ...;
if (func(transaction) == comparand) { ... }
Func-Func=。。。;
布尔比较数=。。。;
交易量=。。。;
if(func(transaction)==比较对象){…}
转换为表达式树的内容:

Expression funcExpression = ... /*LambdaExpression<Func<Transaction,bool>>*/;
Expression comparandExpression = Expression.Constant(true);
Expression transactionArg = /*e.g.*/Expression.Constant(transaction);
Expression funcResultExpression = Expression.Call(funcExpression, "Invoke", null, transactionArg);
Expression equalityTestExpression = Expression.Equal(funcResultExpression, comparandExpression);
Expression funcExpression=…/*LambdaExpression*/;
表达式比较表达式=表达式常数(真);
表达式transactionArg=/*例如.*/Expression.Constant(事务);
表达式funcResultExpression=Expression.Call(funcExpression,“Invoke”,null,transactionArg);
表达式equalityTestExpression=表达式.Equal(funcResultExpression,CompariandExpression);
Expression funcExpression = ... /*LambdaExpression<Func<Transaction,bool>>*/;
Expression comparandExpression = Expression.Constant(true);
Expression transactionArg = /*e.g.*/Expression.Constant(transaction);
Expression funcResultExpression = Expression.Call(funcExpression, "Invoke", null, transactionArg);
Expression equalityTestExpression = Expression.Equal(funcResultExpression, comparandExpression);