【问题标题】:Will this approach to MVVM produce memory leaks?这种 MVVM 方法会产生内存泄漏吗?
【发布时间】:2015-03-12 14:20:24
【问题描述】:

我发现键入和重新键入引发属性更改事件的相同属性 getter 和 setter 很乏味,并且还可能容易出错,因为属性名称是作为类型化字符串传递的。在寻找更简单的方法后,我创建了以下泛型类:

public class ObservableProperty<T> : INotifyPropertyChanged
{
    private T _backingField;
    public T Value
    {
        get { return this._backingField; }
        set
        {
            if (!EqualityComparer<T>.Default.Equals(this._backingField, value))
            {
                this._backingField = value;
                this.TriggerPropertyChangedEvent();
            }
        }
    }

    /// <summary>
    /// Creates an observable property with a default initial value.
    /// </summary>
    public ObservableProperty() : this(default(T)) { }

    /// <summary>
    /// Creates an observable property with the specified initial value.
    /// </summary>
    /// <param name="initialValue">The value to initialize the observable property to.</param>
    public ObservableProperty(T initialValue)
    {
        this.Value = initialValue;
    }

    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;

    protected void TriggerPropertyChangedEvent([CallerMemberName]string propertyName = null)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion // INotifyPropertyChanged Implementation
}

现在无需在整个 ViewModel 上实现 INotifyPropertyChanged 并手动输入所有支持字段和属性 getter 和 setter,只需:

public ObservableProperty<string> BindableText { get; private set; }

然后在构造函数中:

this.BindableText = new ObservableProperty<string>("Default Text");

视图现在将绑定到 XAML 中的 BindableText.Value。

所以每个属性都会有自己的 INotifyPropertyChanged 实现,自己成为一个迷你视图模型,创建这些实例的模型和视图模型根本不需要实现接口。

这很好用,可以绑定的属性很容易创建。 ViewModel 甚至可以引用模型上的可观察属性,例如:

public ObservableProperty<int> MyNumber { get { return MyModel.Number; } }

这样视图就不会直接绑定到模型上的属性,只能通过它们的视图模型间接绑定。

我的问题是,由于我没有很多经验,因此采用这种方法是否会出现任何潜在的软内存泄漏,我可以采取某种措施来应对? p>

【问题讨论】:

  • 仅通过查看代码几乎不可能检测到内存泄漏,您需要分析您的应用程序才能真正查看它是否确实在泄漏内存。
  • 有一种更好的方法可以避免INotifyPropertyChanged 中涉及表达式的拼写错误,例如stackoverflow.com/questions/2711435/…
  • 您可能希望使用参数属性CallerMemberName 让编译器为您插入属性名称。
  • ObservableProperty 类确实已经在其 INotifyPropertyChanged 的​​实现中使用了 CallerMemberName 属性。我在编写类之前就开始使用它,但是写出所有的属性 getter 和 setter 仍然很乏味。
  • 米歇尔·德·奈斯,谢谢。你是对的。但是,我想知道是否有一种“防御性编程”方法来确保所有订阅者都取消订阅这些属性,这样就不会成为问题。

标签: c# mvvm memory-leaks inotifypropertychanged


【解决方案1】:

采用这种方法会不会有任何潜在的软内存泄漏,我可以采取某种措施来应对?

发生内存泄漏的风险与标准 INotifyPropertyChange 方法相同:

  1. 如果这些ObservableProperties 用于XAML 中的绑定,则不会发生内存泄漏,因为WPF 使用Weak Events 来绑定实现INotifyPropertyChange 接口的对象的属性。

  2. 如果在代码中使用这些ObservableProperties 来订阅INotifyPropertyChange 事件,则可能是内存泄漏。

例如,如果ViewModel 订阅了ModelObservableProperty 对象的INotifyPropertyChange 事件,那么在Model 被垃圾回收或ViewModel 取消订阅之前,此ViewModel 将不会被垃圾回收.如果为一个 Model 创建了多个 ViewModels,则此泄漏可能会很明显。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 2010-10-08
    • 1970-01-01
    相关资源
    最近更新 更多