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

tob*_*777 2 c# lambda

给定以下课程

public class Person
{
    public string Name { get; }
    public List<Person> Friends { get; }
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种在使用 Expression> 时获取以下字符串“Friends.Name”的方法。

这是我想要做的伪代码:

Expression<Func<Person,string>> exp = x => x.Friends.Name
Run Code Online (Sandbox Code Playgroud)

由于明显的原因,这不会编译。

我怎样才能做到这一点?即使您没有代码,通用方法也能解决问题,因为我对此缺乏灵感。

谢谢

Den*_*nis 5

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

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}";
    }
Run Code Online (Sandbox Code Playgroud)

用法:

var path = GetPath(_ => _.Friends.Select(f => f.Name)); // Friends.Name
Run Code Online (Sandbox Code Playgroud)

但这是一个相当简单的情况,而在我看来,您正在执行类似于Include实体框架中的方法的操作。
因此,如果您想解析更复杂的表达式,如下所示:

_ => _.Friends.Select(f => f.Children.Select(c => c.Age))
Run Code Online (Sandbox Code Playgroud)

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

  • @Fabjan:这是 C# 6 功能 (https://msdn.microsoft.com/en-us/library/dn961160.aspx)。要编译 VS2013 及更低版本的代码,请将此行替换为“string.Format”或只是字符串连接。 (2认同)