gpt4 book ai didi

c# - 从 MemberExpression 中获取对象?

转载 作者:IT王子 更新时间:2023-10-29 03:59:36 26 4
gpt4 key购买 nike

所以,假设我在 C# 中有以下表达式:

Expression<Func<string>> expr = () => foo.Bar;

如何提取对 foo 的引用?

最佳答案

I had the same problem, but somewhat more complex, and Darin Dimitrov's answer gave me a good start. I'll post my results here, despite the fact that this is an "old" question .


情况一:根对象是实例成员

    this.textBox.Text    // where 'this' has type 'Form'

...等价于下面的表达式树:

.                                    +====================+
. | MemberExpression |
. +====================+
# | |
# .Expression | | .Member
# v v
. +------------------+ +------------+
. | MemberExpression | | MemberInfo |
. +------------------+ +------------+
# | | .Name = "Text"
# .Expression | | .Member .MemberType = Property
# v v
. +--------------------+ +------------+
. | ConstantExpression | | MemberInfo |
. +--------------------+ +------------+
# .Value = this .Name = "textBox"
# .Type = typeof(Form) .MemberType = Field

在此表达式树中,您实际获得对象引用的唯一位置是来自 ConstantExpression:它允许您获得对 this 的引用。因此,在这棵树中获取任何对象引用的基本思路如下:

  1. 沿着 .Expression 轴进入表达式树,直到到达 ConstantExpression 节点。

  2. 获取该节点的 .Value 属性。这是根对象引用(即上例中的 this)。

  3. 使用表达式树中的反射和 MemberInfo 节点,获取对象引用并按照您的方式返回“向上”表达式树。

下面是一些演示这一点的代码:

Expression expr = ...;   // <-- initially set to the expression tree's root

var memberInfos = new Stack<MemberInfo>();

// "descend" toward's the root object reference:
while (expr is MemberExpression)
{
var memberExpr = expr as MemberExpression;
memberInfos.Push(memberExpr.Member);
expr = memberExpr.Expression
}

// fetch the root object reference:
var constExpr = expr as ConstantExpression;
var objReference = constExpr.Value;

// "ascend" back whence we came from and resolve object references along the way:
while (memberInfos.Count > 0) // or some other break condition
{
var mi = memberInfos.Pop();
if (mi.MemberType == MemberTypes.Property)
{
objReference = objReference.GetType()
.GetProperty(mi.Name)
.GetValue(objReference, null);
}
else if (mi.MemberType == MemberTypes.Field)
{
objReference = objReference.GetType()
.GetField(mi.Name)
.GetValue(objReference);
}
}

情况2:根对象是静态类成员

    Form.textBox.Text    // where 'textBox' is a static member of type 'Form'

... 导致不同的表达式树。注意左下角的空引用:

.                                    +====================+
. | MemberExpression |
. +====================+
# | |
# .Expression | | .Member
# v v
. +------------------+ +------------+
. | MemberExpression | | MemberInfo |
. +------------------+ +------------+
# | | .Name = "Text"
# .Expression | | .Member .MemberType = Property
# v v
. null +------------+
. | MemberInfo |
. +------------+
# .Name = "textBox"
# .MemberType = Field
# .DeclaringType = typeof(Form)

在这里,您不能通过等待 ConstantExpression 来停止“下降”阶段。相反,当您到达空引用时,您将停止下降。接下来,您按如下方式检索根对象引用:

var mi = memberInfos.Pop();
objReference = mi.DeclaringType
.GetField(member.Name, BindingFlags.Static) // or .GetProperty!
.GetValue(null);

从那里开始的“上升”阶段与以前相同。


当然还有更多的情况(例如命名参数作为根对象),但我希望到现在为止,我已经了解了基本的想法,所以我会在这里打断。

关于c# - 从 MemberExpression 中获取对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1613239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com