简体   繁体   English

构造具有链接属性的表达式树?

[英]Construct expression tree with chained properties?

I have a method that accepts Expression<Func<T, string>> , for example x => x.Name , and a term, and returns x => x.Name.Contains(term) : 我有一个接受Expression<Func<T, string>> ,例如x => x.Name和一个条件,然后返回x => x.Name.Contains(term)

Given the model; 给定模型;

class X
{
    public Y Y {get; set;}
}

class Y
{
    public string Z {get; set;}
}

It works well for GenerateForMember<Y>(y => yZ, "foobar") , but currently don't work for GenerateForMember<X>(x => xYZ, "foobar") . 它对于GenerateForMember<Y>(y => yZ, "foobar")效果很好,但目前不适用于GenerateForMember<X>(x => xYZ, "foobar") It gives the exception 它给出了例外

'Z' is not a member of 'UserQuery+X' “ Z”不是“ UserQuery + X”的成员

How to I update my method to work with chained properties? 如何更新我的方法以使用链接属性?

Method is as follows: 方法如下:

protected Expression<Func<T, bool>> GenerateForMember<T>(Expression<Func<T,string>> expression, string term)
{
    var type = typeof(T);

    var memberExpression = ((expression.Body.NodeType == ExpressionType.Convert) 
        ? ((UnaryExpression)expression.Body).Operand 
        : expression.Body) as MemberExpression;

    ParameterExpression parameter = Expression.Parameter(type, type.Name.ToLower());
    MemberExpression member = Expression.PropertyOrField(parameter, memberExpression.Member.Name);

    var propertyInfo = memberExpression.Member as PropertyInfo;

    var memberType = propertyInfo == null
        ? ((FieldInfo) memberExpression.Member).FieldType
        : propertyInfo.PropertyType;


    ConstantExpression constant = Expression.Constant(term, typeof(string));

    MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
    var containsMethodExp = Expression.Call(member, method, constant);

    return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameter);
}

You are dissecting the original expression and later re-construct it again. 您将剖析原始表达式,然后再重新构造它。 This is not necessary. 这不是必需的。 You can use expression.Body directly in order to create the method call. 您可以直接使用expression.Body来创建方法调用。 Like this, it should work with any lambda expression. 这样,它就可以与任何lambda表达式一起使用。

var type = typeof(T);

ParameterExpression parameter = Expression.Parameter(type, type.Name.ToLower());

ConstantExpression constant = Expression.Constant(term, typeof(string));

MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var containsMethodExp = Expression.Call(expression.Body, method, constant);

return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameter);

Try this: 尝试这个:

protected Expression<Func<T, bool>> GenerateForMember<T>(Expression<Func<T, string>> expression, string term)
{
    ConstantExpression constant = Expression.Constant(term, typeof(string));

    MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });

    var containsMethodExp = Expression.Call(expression.Body, method, constant);

    return Expression.Lambda<Func<T, bool>>(containsMethodExp, expression.Parameters[0]);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM