检查Expression是否包含特定属性

时间:2017-05-12 18:50:30

标签: c#

给定一个具有如此签名的方法:

MyMethod(params Expression<Func<Subscription, object>>[] fields)

这叫做:

MyMethod(x=> x.SomeProperty)

如何查看传递给MyMethod的表达式?例如:

MyMethod(Expression<Func<Subscription, object>>[] fields) {
    //using contains like this doesnt seem to work
    if(fields.Contains(x=> x.SomeProperty)) {...}
}

2 个答案:

答案 0 :(得分:2)

您可以实现ExpressionVisitor,并在表达式树中查找名为SomeProperty的属性:

internal class Finder : ExpressionVisitor {
    private readonly string toFind;
    public Finder(string toFind) {
        this.toFind = toFind;
    }
    public bool IsFound { get; private set; }
    protected override Expression VisitMember(MemberExpression node) {
        IsFound |= node.Member.MemberType == MemberTypes.Property && node.Member.Name == toFind;
        return base.VisitMember(node);
    }
}

使用访客如下:

static void MyMethod(params Expression<Func<Program,object>>[] fields) {
    foreach (var fieldExpr in fields) {
        var finder = new Finder("Foo");
        finder.Visit(fieldExpr);
        if (finder.IsFound) {
            Console.WriteLine("Expression {0} references 'Foo'", fieldExpr);
        } else {
            Console.WriteLine("Expression {0} does not reference 'Foo'", fieldExpr);
        }
    }
}

调用这样的方法

MyMethod(e => e.Foo, e => e.Bar, e => e.Bar != null ? e.Foo : e.Bar);

生成此输出:

Expression e => e.Foo references 'Foo'
Expression e => e.Bar does not reference 'Foo'
Expression e => IIF((e.Bar != null), e.Foo, e.Bar) references 'Foo'

Demo.

答案 1 :(得分:0)

表达式非常通用。您可能首先需要过滤MemberExpression的字段:

public static void MyMethod(params Expression<Func<Subscription, object>>[] fields)
{
    var memberExpressions = fields
        .Where(f => typeof(MemberExpression).IsAssignableFrom(f.Body.GetType()))
        .Select(f => (MemberExpression)f.Body)
        .ToList();
    if (memberExpressions.Any(ex => 
        ex.Member.MemberType == MemberTypes.Property &&
        ex.Member.Name == "SomeProperty"))
    {
        Console.WriteLine("At least one of the fields expressions passed to this function were x => x.SomeProperty");
    }
}