【问题标题】:Get parent property from Expression function从表达式函数获取父属性
【发布时间】:2014-11-12 15:12:23
【问题描述】:

假设我有以下课程:

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 与之通信的数据库。

这个数据库得到了通常的关系,比如: 表螺纹 用户 ID -> 用户.用户 ID

现在提取到模型。按照上面的例子:

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 的信息。

也许这说明了所有这一切的目的,也可能没有。

【问题讨论】:

  • 如果您尝试以这种方式获取信息,那么您将强制您接受的 lambda 调用参数属性的属性,并执行其他任何操作会破坏你的代码。在更高的层次上,你实际上想用这个表达做什么?可能有更好的方法来获取您想要的信息,而不会对 lambda 所需的确切格式进行如此严格的限制。
  • 那么您肯定需要以更通用的方式解决这个问题。听起来您正在从头开始编写整个查询提供程序。这是一个极其涉及的过程,既非常困难,又非常冗长/乏味。在 SO 答案的范围内,真的没有任何方法可以描述如何适当地解决这个问题。
  • @Ekenstein 我看不出这个解决方案在哪里试图解决这个问题......?这个问题听起来也很宽泛,不适合 SO。
  • @Ekenstein 因此,如果您在我删除它之前设法抓住了我的答案,那么这是获得您想要的东西的一种方式。代替 cmets,我觉得这个问题可能应该被关闭。
  • 为澄清而编辑了帖子。

标签: c# properties lambda expression parent


【解决方案1】:

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

第一个是成员属性。这是被调用的 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;
    }
}

当这样调用时:

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

它会输出:

  • 价值
  • 内部模型

这个:

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

将输出:

  • 长度
  • AssemblyQualifiedName
  • 声明类型
  • 入口点

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    相关资源
    最近更新 更多