如何从()=> foo.Title表达式获取对象实例

我有一个带有属性的简单类

class Foo { string Title { get; set; } } 

我试图通过调用函数来简化数据绑定

 BindToText(titleTextBox, ()=>foo.Title ); 

这被宣布为

 void BindToText(Control control, Expression<Func> property) { var mex = property.Body as MemberExpression; string name = mex.Member.Name; control.DataBindings.Add("Text", ??? , name); } 

那我该怎么办??? 对于我的Foo类的实例。 如何从lambda表达式中获取对调用foo实例的引用?

编辑:实例应该在某处,因为我可以调用property.Compile()并创建一个在我的BindToText函数中使用foo实例的委托。 所以我的问题是,如果可以在不添加函数参数中实例的引用的情况下完成此操作。 我呼吁Occum的Razor提供最简单的解决方案。

编辑2:许多人没有注意到的是在我的函数中访问foo实例时存在的闭包 ,如果我编译lambda。 为什么编译器知道在哪里找到实例,我不知道? 我坚持认为必须有一个答案, 不必通过额外的论证。


感谢VirtualBlackFox的解决方案是这样的:

 void BindText(TextBoxBase text, Expression<Func> property) { var mex = property.Body as MemberExpression; string name = mex.Member.Name; var fex = mex.Expression as MemberExpression; var cex = fex.Expression as ConstantExpression; var fld = fex.Member as FieldInfo; var x = fld.GetValue(cex.Value); text.DataBindings.Add("Text", x, name); } 

这让我只需输入BindText(titleText, () => foo.Title);

您想要的小LINQPad样本:

 void Foo(Expression> prop) { var propertyGetExpression = prop.Body as MemberExpression; // Display the property you are accessing, here "Height" propertyGetExpression.Member.Name.Dump(); // "s" is replaced by a field access on a compiler-generated class from the closure var fieldOnClosureExpression = propertyGetExpression.Expression as MemberExpression; // Find the compiler-generated class var closureClassExpression = fieldOnClosureExpression.Expression as ConstantExpression; var closureClassInstance = closureClassExpression.Value; // Find the field value, in this case it's a reference to the "s" variable var closureFieldInfo = fieldOnClosureExpression.Member as FieldInfo; var closureFieldValue = closureFieldInfo.GetValue(closureClassInstance); closureFieldValue.Dump(); // We know that the Expression is a property access so we get the PropertyInfo instance // And even access the value (yes compiling the expression would have been simpler :D) var propertyInfo = propertyGetExpression.Member as PropertyInfo; var propertyValue = propertyInfo.GetValue(closureFieldValue, null); propertyValue.Dump(); } void Main() { string s = "Hello world"; Foo(() => s.Length); } 

别。 只需修改方法以获取另一个参数,如#3444294中所述 。 对于您的示例,它可能是这样的:

 void BindToText(Control control, T dataSource, Expression> property) { var mex = property.Body as MemberExpression; string name = mex.Member.Name; control.DataBindings.Add("Text", dataSource, name); } 

并会被称为

 BindToText(titleTextBox, foo, ()=>foo.Title ); 

还不错,但很容易理解。 没有魔法发生。 ;)

像下面这样的东西应该工作:

 void BindToText(Control control, Expression> property) { var mex = property.Body as MemberExpression; string name = mex.Member.Name; var fooMember = mex.Expression as MemberExpression; var fooConstant = fooMember.Expression as ConstantExpression; var foo = fooConstant.Value; control.DataBindings.Add("Text", foo, name); } 

如果这对您不起作用,请告诉我。