如何从字符串为深层属性创建表达式树/lambda
给定一个字符串:“Person.Address.Postcode”,我希望能够在 Person 的实例上获取/设置此邮政编码属性。 我怎样才能做到这一点? 我的想法是用“.”分割字符串。 然后迭代这些部分,查找前一个类型的属性,然后构建一个看起来像这样的表达式树(对伪语法表示歉意):
(person => person.Address) address => address.Postcode
不过,我在实际创建表达式树时遇到了真正的麻烦! 如果这是最好的方法,有人可以建议如何去做,或者有更简单的选择吗?
谢谢
安德鲁
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
public Address Address{ get; set; }
public Person()
{
Address = new Address();
}
}
public class Address
{
public string Postcode { get; set; }
}
Given a string: "Person.Address.Postcode" I want to be able to get/set this postcode property on an instance of Person. How can I do this? My idea was to split the string by "." and then iterate over the parts, looking for the property on the previous type, then build up an expression tree that would look something like (apologies for the pseudo syntax):
(person => person.Address) address => address.Postcode
I'm having real trouble acutally creating the expression tree though! If this is the best way, can someone suggest how to go about it, or is there an easier alternative?
Thanks
Andrew
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
public Address Address{ get; set; }
public Person()
{
Address = new Address();
}
}
public class Address
{
public string Postcode { get; set; }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
听起来您是通过常规反射进行排序的,但作为信息,为嵌套属性构建表达式的代码将非常类似于 此排序代码。
请注意,要设置值,您需要在属性上使用
GetSetMethod()
并调用它 - 没有内置表达式用于在构造后赋值(尽管它是 4.0 中支持)。(编辑)像这样:
It sounds like you're sorted with regular reflection, but for info, the code to build an expression for nested properties would be very similar to this order-by code.
Note that to set a value, you need to use
GetSetMethod()
on the property and invoke that - there is no inbuilt expression for assigning values after construction (although it is supported in 4.0).(edit) like so:
为什么不使用递归? 就像是:
Why you don't use recursion? Something like:
如果有人对简单反射方法之间的性能权衡感兴趣(也是很好的例子此处和此处)和Marc的表达式构建方法...
我的测试涉及获得相对较深的属性(ABCDE)10,000次。
显然,这是一个非常具体的测试,我没有考虑优化或设置属性,但我认为 26 倍的性能提升值得注意。
If anyone is interested in the performance trade-off between the simple reflection approach (also nice examples here and here) and Marc's Expression-building approach...
My test involved getting a relatively deep property (A.B.C.D.E) 10,000 times.
Obviously this is a very specific test, and I haven't considered optimisations or setting properties, but I think a 26x performance hit is worth noting.
您想考虑通过 TypeConverter 或其他来源提供您自己的 PropertyDescriptor。
我已经完全实现了您为当前项目所描述的内容(抱歉,商业,否则我会分享),通过从 BindingSource 派生并通过那里提供信息。
这个想法如下:
一旦你拥有了类型,你需要做的就是为属性的 getter 和 setter 创建小“堆栈”,并且可以通过遍历类型的属性树及其属性广度来收集这些“堆栈”首先,将深度限制为指定的级别数,并根据您的数据结构删除循环引用。
我非常成功地将它与 Linq2SQL 对象结合使用,并与它们的绑定列表结合使用:)
You want to look at providing your own PropertyDescriptor's via TypeConverter or some other source.
I have implemented exactly what you describe for current project (sorry, commercial, else I would share), by deriving from BindingSource, and providing the information via there.
The idea is as follows:
All you need to do is, once you have the type is to create little 'stacks' for the getter and setters of properties, and those you can collect via walking the property tree of the type and its properties breadth first, limiting the depths to a specified number of levels and removing circular references depending on your data structures.
I am using this quite successfully with Linq2SQL objects and in combination with their binding lists :)
表达式树
Expression Tree