using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
namespace System.Application.Mvvm
{
///
/// 属性更改通知事件
///
[Serializable]
public class NotificationObject : INotifyPropertyChanged
{
///
/// 属性更改通知事件
///
[field: NonSerialized]
public event PropertyChangedEventHandler? PropertyChanged;
///
/// 引发属性更改通知事件
///
///
/// () => lambda表达式属性
/// () => 指定了具有非属性格式的Lambda表达式
[NotifyPropertyChangedInvocator]
// ReSharper disable once UnusedParameter.Global
protected virtual void RaisePropertyChanged(ref T source, [NotNull] Expression> propertyExpression)
{
if (propertyExpression == null) throw new ArgumentNullException(nameof(propertyExpression));
if (!(propertyExpression.Body is MemberExpression))
throw new NotSupportedException("此方法仅允许使用 ()=> properties形式的lambda表达式");
var memberExpression = (MemberExpression)propertyExpression.Body;
RaisePropertyChanged(memberExpression.Member.Name);
}
///
/// 引发属性更改通知事件
///
/// 属性名称
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged([CallerMemberName][DisallowNull] string propertyName = "")
{
var threadSafeHandler = Interlocked.CompareExchange(ref PropertyChanged, null, null);
threadSafeHandler?.Invoke(this, EventArgsFactory.GetPropertyChangedEventArgs(propertyName));
}
///
/// 如果该值与上一个值不同,则将其更改并引发属性更改通知事件。
///
/// 属性泛型
/// 原始值
/// 新值
/// 属性名称数组,当此属性更改时会触发PropertyChanged事件
/// 属性名称
/// 值是否已更改
[NotifyPropertyChangedInvocator]
protected bool RaisePropertyChangedIfSet(ref T source, T value, string[]? relatedProperties = null,
[CallerMemberName] string propertyName = null)
{
// 如果值相同则什么都不做
if (EqualityComparer.Default.Equals(source, value))
return false;
source = value;
RaisePropertyChanged(propertyName);
if (relatedProperties == null) return true;
foreach (var p in relatedProperties)
RaisePropertyChanged(p);
return true;
}
///
/// 如果该值与上一个值不同,则将其更改并引发属性更改通知事件。
///
/// 属性泛型
/// 原始值
/// 新值
/// 属性名称字符串,当此属性更改时会触发PropertyChanged事件
/// 属性名称
/// 值是否已更改
[NotifyPropertyChangedInvocator]
protected bool RaisePropertyChangedIfSet(ref T source, T value, string relatedProperty,
[CallerMemberName] string propertyName = null)
{
return RaisePropertyChangedIfSet(ref source, value, new[] { relatedProperty }, propertyName);
}
}
}