如何实现 INotifyPropertyChanged 使用名称而不是魔术字符串

本文关键字:字符串 魔术 何实现 实现 INotifyPropertyChanged | 更新日期: 2023-09-27 18:34:11

我正在阅读有关 C# 6 中新的 nameof 关键字的信息。我想知道如何使用此关键字实现INotifyPropertyChanged,先决条件是什么(当然除了 C# 6 之外)以及它将如何影响我的 MVVM 应用程序的性能?

如何实现 INotifyPropertyChanged 使用名称而不是魔术字符串

它看起来像这样:

public string Foo
{
   get
   {
      return this.foo;
   }
   set
   {
       if (value != this.foo)
       {
          this.foo = value;
          OnPropertyChanged(nameof(Foo));
       }
   }
}

nameof(Foo)将在编译时替换为"Foo"字符串,因此它应该非常高效。这不是反思。

这只是使用nameof()而不是魔术字符串的问题。下面的示例来自我关于该主题的博客文章:

private string currentTime;
public string CurrentTime
{
    get
    {
        return this.currentTime;
    }
    set
    {
        this.currentTime = value;
        this.OnPropertyChanged(nameof(CurrentTime));
    }
}

由于它是在编译时计算的,因此它比任何当前的替代方案(博客文章中也提到)都更具性能。

下面是

使用新的 C# 6.0 糖的类的完整代码示例:

public class ServerViewModel : INotifyPropertyChanged {
    private string _server;
    public string Server {
        get { return _server; }
        set {
            _server = value;
            OnPropertyChanged(nameof(Server));
        }
    }
    private int _port;
    public int Port {
        get { return _port; }
        set {
            _port = value;
            OnPropertyChanged(nameof(Port));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName) => 
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

这样,您可以获得nameof()运算符、空条件运算符?. 和一个表达式体函数(OnPropertyChanged定义)。

我发现使用PropertyChanged.Fody要容易得多,因为您最终会得到更少的错误和更干净的代码,请参阅-https://github.com/Fody/PropertyChanged

您所要做的就是用ImplementPropertyChanged属性标记您的类:

[ImplementPropertyChanged]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }
    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
}

构建后,它被转换为:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }
    string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }
    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

请参阅 INotifyPropertyChanged.PropertyChanged Event 的文档

private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }