一尘不染

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

c#

微软应该为它实现一些简单的功能INotifyPropertyChanged,例如在自动属性中,只需指定{get; set; notify;}
我认为这样做很有意义。还是有任何并发​​症要做?

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

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


阅读 317

收藏
2020-05-19

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

这不是很大;如果需要,它也可以用作基类。在bool从回SetField告诉你,如果它是一个空操作,如果你想申请其他逻辑。


甚至更容易使用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);
}
2020-05-19