从Expression函数获取父属性

Eke*_*ein 5 c# lambda expression properties parent

所以我要说我有以下几个类:

public class Model {
    public AnotherModel InnerModel {
        get;
        set;
    }
}

public class AnotherModel {
    public String Value{
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我有以下功能:

public static void Foo<T, U>(Expression<Func<T, U>> func) {
     // Get the property info from func
}
Run Code Online (Sandbox Code Playgroud)

我现在想做的是以下内容:

Foo<Model, String>(o => o.InnerModel.Value)
Run Code Online (Sandbox Code Playgroud)

问题出现了:

我知道您可以通过执行以下操作从表达式func中获取PropertyInfo:

PropertyInfo propertyInfo = (PropertyInfo)((MemberExpression)func.Body).Member;
Run Code Online (Sandbox Code Playgroud)

这将获得Value属性的PropertyInfo.但是,我还想获取有关parent属性的信息,即InnerModel属性.

到目前为止我所知道的是我可以做到以下几点:

((MemberExpression)func.Body).Expression
Run Code Online (Sandbox Code Playgroud)

获取父属性的信息.但是,似乎无法从Expression本身提取PropertyInfo.

有没有办法实际检索Expression的PropertyInfo?

编辑:澄清一下,这可能是尝试它的一种不好的方式但是这里:我不能使用EntityFramework,只是为了确保理解它.

我需要通过API与数据库进行通信.

这个数据库得到了通常的关系,如方式:表线程UserID - > Users.UserID

现在提取到模型.要遵循上面的例子:

class Thread {
    [Reference(USER_USERID)]
    [TableKey(THREAD_USERID)]
    public User user {
        get;set;
    }
}

class User {
     [TableKey(USER_USERID)]
     public int UserId {
         get;set;
     }
}
Run Code Online (Sandbox Code Playgroud)

现在我想对此进行查询.所以我想"嘿,让我们使用表达式简化最终用户如何询问东西,是的."

所以,我们可以做类似EqualTo的事情(o => o.user.UserId,1);

但是,由于TableKey属性与引用键不同,我需要首先从数据库中获取来自Thread表的userId,然后使用该Id开始向User表询问具有该id的信息.

也许这澄清了所有这一切的目的,或者可能没有.

And*_*ord 5

正如您已经确定的那样,表达式的主体是 MemberExpression。我们需要查看 MemberExpression 的两个属性。

第一个是 Member 属性。这是被调用的 MemberInfo。在您的示例中,这是 Value 属性。我们需要查看的第二个属性是 Expression 属性。这就是调用成员表达式的内容。在您的示例中,这是 {o.InnerModel}。

{o.InnerModel} 是另一个 MemberExpression。Member 是 InnerModel,Expression 是 o。

这是一些获取 MemberInfos 链的代码

public static void Foo<T, U>(Expression<Func<T, U>> func)
{
    var memberExp = func.Body as MemberExpression;
    while (memberExp != null)
    {
        var memberInfo = memberExp.Member;
        Console.WriteLine(memberInfo.Name);
        memberExp = memberExp.Expression as MemberExpression;
    }
}
Run Code Online (Sandbox Code Playgroud)

当这样调用时:

Foo<Model, String>(o => o.InnerModel.Value);
Run Code Online (Sandbox Code Playgroud)

它会输出:

  • 价值
  • 内部模型

这个:

Foo<Assembly, int>(a => a.EntryPoint.DeclaringType.AssemblyQualifiedName.Length);
Run Code Online (Sandbox Code Playgroud)

将输出:

  • 长度
  • 装配限定名称
  • 声明类型
  • 入口点