使用linq表达式的typesafe NotifyPropertyChanged

时间:2010-04-26 06:18:29

标签: wpf mvvm expression-trees inotifypropertychanged

表单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?

6 个答案:

答案 0 :(得分:5)

引发这种情况的代码是什么样的?我是猜测它是这样的:

NotifyOfPropertyChange(() => SomeVal);

暗示:

NotifyOfPropertyChange(() => this.SomeVal);

捕获this,并且非常多意味着表达式树必须每次都从头开始构建(带Expression.Constant)。然后你每次解析它。所以开销肯定是非平凡的。

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

答案 1 :(得分:2)

Emiel Jongerius与各种INotifyPropertyChanged实现的性能比较良好。

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

最重要的是,如果您在UI上使用INotifyPropertyChanged进行数据绑定,则不同版本的性能差异无关紧要。

答案 2 :(得分:1)

如何使用事实上的标准

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

Typesafe且没有性能损失:NotifyPropertyWeaver扩展。它会在编译之前自动添加所有通知...