展平Lambda表达式以访问集合属性成员名称

时间:2015-09-29 11:31:44

标签: c# lambda

给出以下课程

public class Person
{
    public string Name { get; }
    public List<Person> Friends { get; }
}

我正在寻找一种方法来获取以下字符串“Friends.Name”,当使用表达式&gt;时。

以下是我想要做的伪代码:

Expression<Func<Person,string>> exp = x => x.Friends.Name

由于显而易见的原因而无法编译。

我怎样才能实现这一目标?即使你没有代码,一般的方法也可以解决问题,因为我缺乏这方面的灵感。

由于

2 个答案:

答案 0 :(得分:4)

使用这种表达方式,你无法得到你想要的东西:

Expression<Func<Person,string>>

因为Person的集合为Friends。实际上,Func的返回类型并不重要。这将有效:

    static string GetPath(Expression<Func<Person, object>> expr)
    {
        var selectMethodCall = (MethodCallExpression)expr.Body;
        var collectionProperty = (MemberExpression)selectMethodCall.Arguments[0];
        var collectionItemSelector = (LambdaExpression)selectMethodCall.Arguments[1];
        var collectionItemProperty = (MemberExpression)collectionItemSelector.Body;

        return $"{collectionProperty.Member.Name}.{collectionItemProperty.Member.Name}";
    }

用法:

var path = GetPath(_ => _.Friends.Select(f => f.Name)); // Friends.Name

但这是一个相当简单的案例,而在我看来,您正在从实体框架中执行类似Include方法的操作。
所以,如果你想解析更复杂的表达式,比如:

_ => _.Friends.Select(f => f.Children.Select(c => c.Age))

你需要以更通用的方式探索表达。

答案 1 :(得分:0)

假设下面是exoression,你可以得到这样的道路:

Expression<Func<Person, string>> exp = x => x.Name; 

var lambdaBody = exp.Body;

if(lambdaBody.NodeType == ExpressionType.MemberAccess)
{
    var memberExpression = lambdaBody as MemberExpression;
    Console.WriteLine(memberExpression.ToString());
}

输出:

x.Name