using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace HKW.HKWUtils.Observable;
///
/// 可观察对象
/// 示例:
/// {
/// int _value = 0;
/// public int Value
/// {
/// get => _value;
/// set => SetProperty(ref _value, value);
/// }
/// }]]>
///
public abstract class ObservableClass
: INotifyPropertyChanging,
INotifyPropertyChanged,
INotifyPropertyChangingX,
INotifyPropertyChangedX
where TObject : ObservableClass
{
public ObservableClass()
{
if (GetType() != typeof(TObject))
throw new InvalidCastException(
$"Inconsistency between target type [{GetType().FullName}] and generic type [{typeof(TObject).FullName}]"
);
}
#region OnPropertyChange
///
/// 设置属性值
///
/// 值
/// 新值
/// 属性名称
/// 成功为 失败为
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool SetProperty(
ref TValue value,
TValue newValue,
[CallerMemberName] string propertyName = null!
)
{
if (EqualityComparer.Default.Equals(value, newValue) is true)
return false;
var oldValue = value;
if (OnPropertyChanging(oldValue, newValue, propertyName))
return false;
value = newValue;
OnPropertyChanged(oldValue, newValue, propertyName);
return true;
}
///
/// 属性改变前
///
/// 旧值
/// 新值
/// 属性名称
/// 取消为 否则为
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool OnPropertyChanging(
object? oldValue,
object? newValue,
[CallerMemberName] string propertyName = null!
)
{
PropertyChanging?.Invoke(this, new(propertyName));
if (PropertyChangingX is null)
return false;
var e = new PropertyChangingXEventArgs(propertyName, oldValue, newValue);
PropertyChangingX?.Invoke((TObject)this, e);
if (e.Cancel)
PropertyChanged?.Invoke(this, new(propertyName));
return e.Cancel;
}
///
/// 属性改变后
///
/// 旧值
/// 新值
/// 属性名称
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual void OnPropertyChanged(
object? oldValue,
object? newValue,
[CallerMemberName] string propertyName = null!
)
{
PropertyChanged?.Invoke(this, new(propertyName));
PropertyChangedX?.Invoke((TObject)this, new(propertyName, oldValue, newValue));
}
#endregion
#region Event
///
public event PropertyChangingEventHandler? PropertyChanging;
///
public event PropertyChangedEventHandler? PropertyChanged;
///
public event PropertyChangingXEventHandler? PropertyChangingX;
///
public event PropertyChangedXEventHandler? PropertyChangedX;
#endregion
}