原来类继承通知接口的写法过于复杂
最基础的类:
//最原始的基础类
class Country
{
public string Code { get; set; }
public string Name { get; set; }
}
继承接口后的写法:
//继承通知接口后的写法
class Country : INotifyPropertyChanging, INotifyPropertyChanged
{
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private void NotifyChanging(string propertyName)
=> PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
private string code;
public string Code
{
get => code;
set
{
NotifyChanging("Code");
code = value;
NotifyChanged("Code");
}
}
private string name;
public string Name
{
get => name;
set
{
NotifyChanging("Name");
name = value;
NotifyChanged("Name");
}
}
}
进行对比发现多了很多代码,而且还额外多了一个private的字段,这样调试也会重复显示相同的数据,改一个名字至少要修改6个地方。
这个问题可以写个抽象类进行解决
//通知抽象类
public abstract class NotifyingEntity : INotifyPropertyChanging, INotifyPropertyChanged
{
//储存属性值的字典
//new() 是C# 9.0 的语法糖
private Dictionary<string, object> property = new();
/// <summary>
/// 设置值时触发通知事件
/// </summary>
/// <param name="value">需要设置的值</param>
/// <param name="propertyName">CallerMemberName属性可以获取调用方的名称(不需要手动设置)</param>
protected void SetValueWithNotify(object value, [CallerMemberName] string propertyName = "")
{
NotifyChanging(propertyName);
if (property.ContainsKey(propertyName))
{
property[propertyName] = value;
}
else
{
property.Add(propertyName, value);
}
NotifyChanged(propertyName);
}
/// <summary>
/// 获得对应的值
/// </summary>
/// <typeparam name="T">需要转换的类型</typeparam>
/// <param name="propertyName">CallerMemberName属性可以获取调用方的名称(不需要手动设置)</param>
protected T GetValue<T>([CallerMemberName] string propertyName = "")
=> property.ContainsKey(propertyName) ? (T)property[propertyName] : default;
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private void NotifyChanging(string propertyName)
=> PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}
继承抽象类以后的代码:
class Country : NotifyingEntity
{
public string Code { get => GetValue<string>(); set => SetValueWithNotify(value); }
public string Name { get => GetValue<string>(); set => SetValueWithNotify(value); }
}
简化后基本和原来一致,只需要注意获取值时候需要指定对应的类型。
利用VS的批量更改功能可以轻易的将{ get; set; } 替换成 { get => GetValue<>(); set => SetValueWithNotify(value); }
然后修改一下对应的类型就行了,更高级一点可以用正则去替换。