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

标签 c# data-binding .net-3.5 expression-trees lambda

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

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

我正在尝试通过调用像这样的函数来简化数据绑定(bind)

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

声明如下

void BindToText<T>(Control control, Expression<Func<T>> property)
{
    var mex = property.Body as MemberExpression;
    string name = mex.Member.Name;

    control.DataBindings.Add("Text", ??? , name);
}

那么我要在 ??? 中为我的 Foo 类的实例放入什么。如何从 lambda 表达式中获取对调用 foo 实例的引用?

编辑: 该实例应该存在于某处,因为我可以调用 property.Compile() 并在我的 BindToText 函数中创建一个使用 foo 实例的委托(delegate)。所以我的问题是,如果不在函数参数中添加对实例的引用,是否可以做到这一点。我呼吁Occum's Razor产生最简单的解决方案。

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


解决方案

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

void BindText<T>(TextBoxBase text, Expression<Func<T>> 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<T>(Expression<Func<T>> 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);
}

关于c# - 如何从 ()=>foo.Title 表达式中获取对象实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5092387/

相关文章:

c# - 播放后自定义编辑器重置?

c# - 从数据库动态绑定(bind) css 类到 asp.net c# 中的 div 标签

c# - Linq 用于不同计数

c# - 使用 Linq 将 xml 解析为 ObservableCollection。使用 wpf c# 将数据绑定(bind)到数据网格

wcf - 是否可以在 WCF 中没有无参数构造函数的情况下序列化对象?

c# - KeyPerFileConfigurationSource 没有同时设置目录路径和忽略条件的选项

javascript - SAPUI5 为可搜索输入命名模型绑定(bind)

c# - 使用 ItemsControl 绑定(bind)对象数组

c# - 带有可选键的多键字典

.net - 向 ADO .NET Entity Framework 添加业务层