【问题标题】:typesafe NotifyPropertyChanged using linq expressions使用 linq 表达式的类型安全 NotifyPropertyChanged
【发布时间】:2011-02-12 06:38:46
【问题描述】:

Form Build your own MVVM 我有以下代码可以让我们进行类型安全的 NotifyOfPropertyChange 调用:

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);
 }

这种方法与标准的简单字符串方法相比在性能方面如何?有时我的属性会以非常高的频率发生变化。我可以安全地使用这种类型安全的方法吗?经过一些初步测试后,它似乎确实产生了一些小差异。这种方法可能会导致多少 CPU 内存负载?

【问题讨论】:

标签: wpf mvvm expression-trees inotifypropertychanged


【解决方案1】:

引发此问题的代码是什么样的?我是这样的:

NotifyOfPropertyChange(() => SomeVal);

这是隐含的:

NotifyOfPropertyChange(() => this.SomeVal);

它捕获了this,并且几乎意味着表达式树必须每次都从头开始构建(使用Expression.Constant)。然后你每次都解析它。所以开销绝对不小。

太多了吗?这是一个只有您可以通过分析和了解您的应用程序才能回答的问题。对于很多 MVC 使用来说,它被认为是可以的,但这并不是(通常)在长时间运行的紧密循环中调用它。基本上,您需要针对所需的性能目标进行分析。

【讨论】:

【解决方案2】:

Emiel Jongerius 对各种 INotifyPropertyChanged 实现具有良好的性能比较。

http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/

底线是,如果您在 UI 上使用 INotifyPropertyChanged 进行数据绑定,那么不同版本的性能差异是微不足道的。

【讨论】:

    【解决方案3】:

    如何使用事实上的标准

    if (propName == value) return;
    propName = value;
    OnPropertyChanged("PropName");
    

    然后创建一个自定义工具,根据此标准检查和重构代码文件。该工具可以是预构建任务,也在构建服务器上。 简单、可靠、执行。

    【讨论】:

      【解决方案4】:

      堆栈遍历很慢,而 lambda 表达式甚至更慢。我们有类似于众所周知的 lambda 表达式的解决方案,但几乎与字符串文字一样快。看 http://zamboch.blogspot.com/2011/03/raising-property-changed-fast-and-safe.html

      【讨论】:

        【解决方案5】:

        我在实现 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);
            }
        

        我希望你也觉得它有用。 :-)

        【讨论】:

        • 请不要在多个问题中发送相同的答案。如果问题是重复的,请留下评论说明(或标记,如果您有足够的声誉)。如果它不是重复的,请调整您对所提问题的回答。
        【解决方案6】:

        类型安全且无性能损失:NotifyPropertyWeaver 扩展。它会在编译之前自动添加所有通知...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-14
          • 1970-01-01
          • 1970-01-01
          • 2015-03-14
          • 1970-01-01
          相关资源
          最近更新 更多