【发布时间】:2010-08-23 21:43:47
【问题描述】:
什么时候需要Expression Trees?
如果可用,请向我们提供真实世界的样本
【问题讨论】:
标签: c# c#-3.0 lambda expression-trees
什么时候需要Expression Trees?
如果可用,请向我们提供真实世界的样本
【问题讨论】:
标签: c# c#-3.0 lambda expression-trees
例如实现 INotifyPropertyChanged 的类型安全实现而不是使用字符串:
public class Sample : TypeSafeNotifyPropertyChanged
{
private string _text;
public string Text
{
get { return _text; }
set
{
if (_text == value)
return;
_text = value;
OnPropertyChanged(() => Text);
}
}
}
public class TypeSafeNotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
PropertyChangedHelper.RaisePropertyChanged(this, propertyExpression, PropertyChanged);
}
}
public static class PropertyChangedHelper
{
public static void RaisePropertyChanged<T>(object sender, Expression<Func<T>> propertyExpression, PropertyChangedEventHandler propertyChangedHandler)
{
if (propertyChangedHandler == null)
return;
if (propertyExpression.Body.NodeType != ExpressionType.MemberAccess)
return;
MemberExpression memberExpr = (MemberExpression)propertyExpression.Body;
string propertyName = memberExpr.Member.Name;
RaisePropertyChanged(sender, propertyName, propertyChangedHandler);
}
private static void RaisePropertyChanged(object sender, string property, PropertyChangedEventHandler propertyChangedHandler)
{
if (propertyChangedHandler != null)
propertyChangedHandler(sender, new PropertyChangedEventArgs(property));
}
}
【讨论】:
() => Text 中,属性名称Text 可能被错误地替换为任何表达式,它仍然可以正常编译。如果程序员不提供成员的标识符,那么它会默默地在运行时引发事件。那么这种“类型安全”在什么意义上是安全的?
每次您想告诉某个函数需要做什么时,您都需要一个表达式树而不是实际执行它。
最好的例子是 LINQ-to-SQL。您传递一个表达式树,以便它可以将此表达式树转换为 SQL。它不会执行表达式,它会检查它并将其转换为 SQL。
【讨论】:
Length (例如)和字符串的其他 c# 属性(例如:子字符串)构建一个大的纯表达式树 - SQL 仍然知道如何执行它吗?我的意思是:它没有“长度”也没有“子字符串”...... sql 仍然知道如何执行命令吗?
表达式树是对某些执行的描述——实际上它是 DOM。当您执行表达式树时,它会被编译并在之后执行。示例是 LinqToSql。当您为 LinqToSql 构建查询时,您是在 IQueryable 上进行的。结果查询是表达式树。当您执行树时,它被“编译”成 SQL 而不是 .NET 并在数据库上执行。
编辑:Here 你有另一个很好的表达式示例,用于在 EF 查询中包含相关实体。
【讨论】:
我最近重构了一个复杂的对象比较器并使用了表达式树。 对象比较器是使用反射实现的,我将其修改为使用反射构建表达式树,然后将表达式树编译为委托。构建和编译委托会产生一些费用,但在编译完成后,它的调用速度几乎是反射解决方案的 100 倍。
【讨论】: