c# - INotifyPropertyChanged 和静态属性

标签 c# .net static inotifypropertychanged

我正在为一个简单的问题纠结。我有一个实现 INotifyPropertyChanged 的类。某些实例属性的 getter 使用静态属性,因此如果静态属性发生变化,它们的值可能会发生变化?这是一个简化的例子。

class ExampleClass : INotifyPropertyChanged
{

    private static int _MinimumLength = 5;
    public static int MinimumLength
    {
        get
        {
            return _MinimumLength;
        }
        set
        {
            if (_MinimumLength != value)
            {
                _MinimumLength = value;
                //WHAT GOES HERE
            }
        }
    }

    private int _length = -1;
    public int length
    {
        get
        {
            return (_length > _MinimumLength) ? _length : _MinimumLength;
        }
        set
        {
            var oldValue = (_length > _MinimumLength) ? _length : _MinimumLength;
            if (_length != value)
            {
                _length = value;
                var newValue = (_length > _MinimumLength) ? _length : _MinimumLength;
                if (newValue != oldValue)
                {
                    OnPropertyChanged("length");
                }
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

显然,如果静态属性 MinimumLength 发生变化,那么每个实例的属性 length 也可能发生变化。但是静态属性应该如何表示实例可能发生的变化呢?它不能调用 OnPropertyChanged,因为它不是静态的。

我可以在所有实例的类级别保留一个列表,并在每个实例上调用一个方法,但不知何故,这感觉有点矫枉过正。或者我可以将静态属性拉出到单例类中,但逻辑上它们存在于类级别。这是否有既定的模式,或者我应该以不同的方式考虑这个问题?

最佳答案

如果您倾向于维持该设计,那么我会采用如下解决方案:

public static int MinimumLength
{
    get { return _MinimumLength; }
    set
    {
        if (_MinimumLength != value)
        {
            _MinimumLength = value;
            OnGlobalPropertyChanged("MinimumLength");
        }
    }
}
static event PropertyChangedEventHandler GlobalPropertyChanged = delegate { };
static void OnGlobalPropertyChanged(string propertyName)
{
    GlobalPropertyChanged(
        typeof (ExampleClass), 
        new PropertyChangedEventArgs(propertyName));
}
public ExampleClass()
{
    // This should use a weak event handler instead of normal handler
    GlobalPropertyChanged += this.HandleGlobalPropertyChanged;
}
void HandleGlobalPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "MinimumLength":
            if (length > MinimumLength)
                length = MinimumLength;
            break;
    }
}

这几乎等同于维护实例列表,但我发现它更易于维护且更清晰。此外,您确实需要使用弱事件处理程序策略,否则,您的实例将不会被垃圾回收,因为它们将始终与充当 GC 根的静态事件相关联。

您可以在以下博客文章中阅读有关弱事件处理程序的更多信息(由我撰写,因此我有偏见):

.NET Weak Event Handlers – Part I

.NET Weak Event Handlers – Part I

在一个不相关的注释中,您的代码当前正在触发属性更改,而实际上属性值并未更改。例如:

  1. 将MinimumLength设置为5;
  2. 将长度设置为 10; (事件触发,因为值从默认值 0 更改为 5)
  3. 设置长度为11; (事件触发,但它不应该触发,因为长度仍然是 5)

关于c# - INotifyPropertyChanged 和静态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14614190/

相关文章:

c# - 如何 - 将一个整数拆分为两个整数?

java - Drools 引用静态场

c# - 如何从查询字符串中获取#值?

.net - 使用 LinkBut​​tons 作为超链接是不好的做法吗?

c++ - C++中包含静态成员的静态成员类

python - 什么时候在 Python 中初始化类变量?

c# - 显示GIF后,C#Windows Form中的WMP停止播放声音

c# - Linq - 使用 not "IN"运算符从文本文件中选择非重复行

c# - 如何将 WPF 窗口嵌入另一个窗口并通过 XAML 或代码调整其大小

.net - 我的 dotnet core Web 服务可以计算对其进行的调用次数吗?