从Expression函数获取父属性

本文关键字:属性 获取 函数 Expression | 更新日期: 2023-09-27 18:30:12

所以假设我有以下类:

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

现在我有以下功能:

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

我现在想做的是:

Foo<Model, String>(o => o.InnerModel.Value)

问题来了:

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

PropertyInfo propertyInfo = (PropertyInfo)((MemberExpression)func.Body).Member;

这将为我获取Value属性的PropertyInfo。但是,我也想获得有关父属性的信息,即InnerModel属性。

到目前为止,我所知道的是我可以做以下事情:

((MemberExpression)func.Body).Expression

以获取父属性的信息。但是,似乎不可能从表达式本身提取PropertyInfo。

是否有某种方法可以实际检索表达式的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;
     }
}

现在我想对此提出疑问。所以我想:"嘿,让我们用表达式来简化最终用户如何索要东西,是的。"

因此,我们可以执行类似EqualTo(o=>o.user.UserId,1)的操作;

然而,由于TableKey属性与引用密钥不同,我需要首先从数据库中从Thread表中获取userId,然后使用该Id开始向User表询问该Id的信息。

也许这澄清了这一切的目的,也许它没有。

从Expression函数获取父属性

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

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

{o.InnerModel}是另一个MemberExpression。成员为InnerModel,表达式为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;
    }
}

当这样调用时:

Foo<Model, String>(o => o.InnerModel.Value);

它将输出:

  • 价值
  • 内部模型

此:

Foo<Assembly, int>(a => a.EntryPoint.DeclaringType.AssemblyQualifiedName.Length);

将输出:

  • 长度
  • 程序集限定名称
  • DeclaringType
  • 入口点