小编典典

实施 INotifyPropertyChanged - 是否存在更好的方法?

all

微软应该已经实现了一些活泼的东西INotifyPropertyChanged,比如在自动属性中,只需指定{get; set; notify;}
我认为这样做很有意义。或者有什么并发症吗?

我们自己可以在我们的属性中实现类似“通知”的东西吗?是否有一个优雅的解决方案可以在您的类中实现,或者唯一的方法是在每个属性中
INotifyPropertyChanged 引发事件。PropertyChanged

如果不能,我们可以写一些东西来自动生成一段代码来引发PropertyChanged 事件吗?


阅读 95

收藏
2022-03-03

共1个答案

小编典典

不使用 postsharp 之类的东西,我使用的最小版本使用如下:

public class Data : INotifyPropertyChanged
{
    // boiler-plate
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    // props
    private string name;
    public string Name
    {
        get { return name; }
        set { SetField(ref name, value, "Name"); }
    }
}

然后,每个属性都类似于:

private string name;
public string Name
{
    get { return name; }
    set { SetField(ref name, value, "Name"); }
}

这不是很大;如果需要,它也可以用作基类。如果您想应用其他逻辑,返回 from 会告诉您它是否是空操作boolSetField


使用 C# 5 甚至更容易:

protected bool SetField<T>(ref T field, T value,
    [CallerMemberName] string propertyName = null)
{...}

可以这样调用:

set { SetField(ref name, value); }

编译器将"Name"自动添加。


C# 6.0 使实现更容易:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

…现在使用 C#7:

protected void OnPropertyChanged(string propertyName)
   => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value,[CallerMemberName] string propertyName =  null)
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

private string name;
public string Name
{
    get => name;
    set => SetField(ref name, value);
}

而且,对于 C# 8 和 Nullable 引用类型,它看起来像这样:

public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

private string name;
public string Name
{
    get => name;
    set => SetField(ref name, value);
}
2022-03-03