是否可以在某个时刻评估选择投影,以获得正在选择哪些属性的列表?
例如,如果我有以下类:
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" };
行的结果?
答案 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);
}