Wpf 使用linq表达式更改typesafe NotifyProperty
Form I具有以下代码,允许我们进行typesafe NotifyOfPropertyChange调用:Wpf 使用linq表达式更改typesafe NotifyProperty,wpf,mvvm,expression-trees,inotifypropertychanged,Wpf,Mvvm,Expression Trees,Inotifypropertychanged,Form I具有以下代码,允许我们进行typesafe NotifyOfPropertyChange调用: public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) { var lambda = (LambdaExpression)property; MemberExpression memberExpression; if (
public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
{
var lambda = (LambdaExpression)property;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else memberExpression = (MemberExpression)lambda.Body;
NotifyOfPropertyChange(memberExpression.Member.Name);
}
public void NotifyOfPropertyChange(表达式属性)
{
var lambda=(LambdaExpression)属性;
成员表达成员表达;
if(lambda.Body是一元表达式)
{
var unaryExpression=(unaryExpression)lambda.Body;
memberExpression=(memberExpression)unaryExpression.Operator;
}
else memberExpression=(memberExpression)lambda.Body;
NotifyOfPropertyChange(memberExpression.Member.Name);
}
这种方法与标准的简单字符串方法性能比较如何?有时我的属性会以非常高的频率变化。我使用这个防打字安全的方法安全吗?经过一些最初的测试,它似乎确实有一点不同。这种方法可能会导致多少CPU内存负载?引起这种情况的代码是什么样子的?我猜是这样的:
NotifyOfPropertyChange(() => SomeVal);
这意味着:
NotifyOfPropertyChange(() => this.SomeVal);
它捕获了这个
,这意味着每次都必须从头开始构造表达式树(使用expression.Constant
)。然后每次都解析它。因此,开销绝对不是微不足道的
是不是太多了?这是一个只有你才能回答的问题,通过分析和了解你的应用程序。对于很多MVC的使用来说,这是可以的,但是(通常)这并不是在一个长期运行的紧密循环中。基本上,您需要根据所需的性能目标进行评测。Emiel Jongerius对各种InotifyProperty更改的实现进行了良好的性能比较
底线是,如果您在UI上使用INotifyPropertyChanged进行数据绑定,那么不同版本的性能差异是微不足道的。堆栈遍历速度较慢,lambda表达式甚至更慢。我们有类似于众所周知的lambda表达式的解决方案,但速度几乎和string literal一样快。看见
我在实现INotifyPropertyChanged的基类中使用了以下方法,它非常简单方便:
public void NotifyPropertyChanged()
{
StackTrace stackTrace = new StackTrace();
MethodBase method = stackTrace.GetFrame(1).GetMethod();
if (!(method.Name.StartsWith("get_") || method.Name.StartsWith("set_")))
{
throw new InvalidOperationException("The NotifyPropertyChanged() method can only be used from inside a property");
}
string propertyName = method.Name.Substring(4);
RaisePropertyChanged(propertyName);
}
我希望您也觉得它有用。:-) 使用事实标准怎么样
if (propName == value) return;
propName = value;
OnPropertyChanged("PropName");
然后创建一个自定义工具,根据此标准检查和重构代码文件。该工具可以是预构建任务,也可以在构建服务器上。
简单、可靠、可执行。类型安全且无性能损失:NotifyPropertyWeaver扩展。它会在编译之前自动添加所有通知…您可能会对此讨论感兴趣:请不要在多个问题上发送相同的答案。如果问题是重复的,请留下一条评论,说明这一点(或者如果你有足够的声誉,请标记)。如果它不是重复的,请根据所问的问题定制您的答案。perf comparations@Simon当然,在c#5中,新的呼叫者姓名属性使它几乎成为一个多余的问题