评估选择投影

时间:2017-10-04 17:32:19

标签: c# expression predicate

是否可以在某个时刻评估选择投影,以获得正在选择哪些属性的列表?

例如,如果我有以下类:

public class Example()
{
    public string Aaa { get; set; }

    public int Bbb { get; set; }

    public string Ccc { get; set; }
}

以及以下选择投影:

Expression<Func<Example, Example>> select = x => new Example { Aaa= x.Aaa, Ccc = x.Ccc };

是否可以解释选择投影以获得var result = new List<string> { "Aaa", "Ccc" };行的结果?

2 个答案:

答案 0 :(得分:3)

执行此类操作的最佳方法是使用ExpressionVisitor

以下是一个例子:

public class MyMemberExpressionVisitor : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Member.MemberType == MemberTypes.Property // is a property
            && node.Expression.NodeType == ExpressionType.Parameter // is from a parameter expression
            && Members.All(s => s != node.Member.Name)) // avoids duplicates
        {
            Members.Add(node.Member.Name);
        }

        return base.VisitMember(node);
    }

    public List<string> Members { get; set; } = new List<string>();
}

然后你可以像这样使用它:

// Complex expressions work too!
Example outsideExample = new Example();
Expression<Func<Example, Example>> expression = x => new Example(
    x.Aaa + outsideExample.Bbb,
    x.Ccc + x.Aaa.Length);

var myVisitor = new MemberExpressionVisitor();
myVisitor.Visit(expression);
Console.WriteLine(string.Join(", ", myVisitor.Members)); // This should print out "Aaa, Ccc"

您可以访问How to: Implement an Expression Tree Visitor了解有关如何实施的更多信息。

答案 1 :(得分:-2)

要查找该表达式中的所有属性表达式,可以使用ExpressionVisitor检查给定表达式中的所有Expression个实例,并查看哪些是属性访问,以及正在访问的属性:

internal class PropertySearchVisitor : ExpressionVisitor
{
    private List<MemberInfo> properties = new List<MemberInfo>();
    public IEnumerable<MemberInfo> Properties => properties;
    protected override Expression VisitMember(MemberExpression node)
    {
        if (node?.Member?.MemberType == MemberTypes.Property)
            properties.Add(node.Member);
        return base.VisitMember(node);
    }
}

一旦你有了,你可以编写一个方法来访问给定的表达式并返回该表达式的属性(或属性名称):

public static IEnumerable<MemberInfo> GetProperties(this Expression expression)
{
    var visitor = new PropertySearchVisitor();
    visitor.Visit(expression);
    return visitor.Properties;
}
public static IEnumerable<string> GetPropertyNames(this Expression expression)
{
    var visitor = new PropertySearchVisitor();
    visitor.Visit(expression);
    return visitor.Properties.Select(property => property.Name);
}