我正在尝试为规则引擎动态地构建表达式,在我尝试允许将嵌套类型和属性指定为操作数之前,一切都很顺利。样品:
表达式生成器

public Expression BuildExpression<T>(string propertyName, Enums.Operator ruleOperator, object value, ParameterExpression parameterExpression)
    {
        ExpressionType expressionType = new ExpressionType();
        Expression body = parameterExpression;

        foreach (var member in propertyName.Split('.'))
        {
            body = MemberExpression.Property(body, member);
        }

        var leftOperand = MemberExpression.PropertyOrField(body, propertyName);
        var rightOperand = Expression.Constant(Convert.ChangeType(value, value.GetType()));
        FieldInfo fieldInfo = expressionType.GetType().GetField(Enum.GetName(typeof(Enums.Operator), ruleOperator));
        var expressionTypeValue = (ExpressionType)fieldInfo.GetValue(ruleOperator);

        return CastBuildExpression(expressionTypeValue, value, leftOperand, rightOperand);
    }

规则引擎
public Func<T, bool>[] CombineRules<T>(Criterion[] criteria)
    {
        List<Func<T, bool>> list = new List<Func<T, bool>>();
        foreach (var criterion in criteria)
        {
            ExpressionBuilder expressionBuilder = new ExpressionBuilder();
            var param = Expression.Parameter(typeof (T));
            Expression expression = expressionBuilder.BuildExpression<T>(criterion.PropertyName,
                    criterion.Operator_, criterion.Value, param);
            Func<T, bool> func = Expression.Lambda<Func<T, bool>>(expression, param).Compile();
            list.Add(func);
        }

        return list.ToArray();
    }

标准
public class Criterion
{
    private bool propertySet;
    public string PropertyName { get; set; }
    public Enums.Operator Operator_ { get; set; }
    public object Value { get; set; }

成员模型
public class MemberModel
{
    public string UserName{ get; set; }
    public PersonalDetailsModel PersonalDetails {get; set;}
}

个性化详细信息模型
    public class PersonalDetailsModel
{
    public int PersonalDetailsId { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Middlename { get; set; }
    public string DateOfBirth { get; set; }
    public string GenderType { get; set; }
    public string SalutationType { get; set; }
}

当我试图将嵌套属性作为左操作数传入ruleengine.combinerules(criteria.toArray())时,就会出现问题;
我得到的“personaldetails.firstname”不是“system.string”类型的成员,尽管它显然是这样。我被困在这件事上有一段时间了,知道是什么原因吗?
任何帮助都将不胜感激。

最佳答案

在这里

    Expression body = parameterExpression;

    foreach (var member in propertyName.Split('.'))
    {
        body = MemberExpression.Property(body, member);
    }

您已经处理了属性路径,因此
  var leftOperand = MemberExpression.PropertyOrField(body, propertyName);

毫无意义,是异常的根源。在您的示例中,body包含类似于p.PersonalDetails.FirstName(字符串)的内容,上面的行试图构建类似于p.PersonalDetails.FirstName.PersonalDetails.FirstName的内容。
改为使用var leftOperand = body;
您可以使用简单的
var leftOperand = propertyName.Split('.')
    .Aggregate((Expression)parameterExpression, Expression.PropertyOrField);

07-24 20:07