Can I use Expression> and reliably see which

2019-02-20 05:10发布

问题:

I'm writing something in the flavour of Enumerable.Where in that takes a predicate of the form Func<T, bool>. If the underlying T implements INotifyPropertyChanged, I'd like to be a bit more intelligent about re-evaluating the predicate.

I'm thinking about changing it to use Expression<Func<T, bool>>, and then using the expression tree to find out which properties are used in the predicate. Then I can have my PropertyChanged handler be a bit more intelligent.

My question: is this feasible? If the predicate's simple (e.g. x => x.Age > 18), then the Expression seems to have everything I need in it. Are there scenarios where I won't be able to see which properties are referenced?

回答1:

Yes, you'll be able to see everything directly referenced. Of course, if someone passes

x => ComputeAge(x) > 18

then you won't necessarily know that ComputeAge refers to the Age property.

The expression tree will be an accurate representation of exactly what's in the lambda expression.



回答2:

Small code example of a visitor that would find directly referenced properties.

public class PropertyAccessFinder : ExpressionVisitor {
    private readonly HashSet<PropertyInfo> _properties = new HashSet<PropertyInfo>();

    public IEnumerable<PropertyInfo> Properties {
        get { return _properties; }
    }

    protected override Expression VisitMember(MemberExpression node) {
        var property = node.Member as PropertyInfo;
        if (property != null)
            _properties.Add(property);

        return base.VisitMember(node);
    }
}

// Usage:
var visitor = new PropertyAccessFinder();
visitor.Visit(predicate);
foreach(var prop in visitor.Properties)
    Console.WriteLine(prop.Name);