由于这是一个非常常见的问题,也是 Miguel 建议的选择 AOP 方法的重要理由,我为Afterthought创建了一个示例,演示了如何实现 INotifyPropertyChanged(拦截属性集以引发事件)。
Afterthought 让您可以非常轻松地描述对属性的拦截,特别是通过为您提供属性的前后值,使属性集拦截变得简单。你会做这样的事情来识别要拦截的属性:
public override void Amend<TProperty>(Property<TProperty> property)
{
// Raise property change notifications
if (property.PropertyInfo.CanRead && property.PropertyInfo.CanWrite)
property.AfterSet = NotificationAmender<T>.OnPropertyChanged<TProperty>;
}
在这种情况下,它调用一个静态方法OnPropertyChanged
,如下所示:
public static void OnPropertyChanged<P>(INotifyPropertyChangedAmendment instance, string property, P oldValue, P value, P newValue)
{
// Only raise property changed if the value of the property actually changed
if ((oldValue == null ^ newValue == null) || (oldValue != null && !oldValue.Equals(newValue)))
instance.OnPropertyChanged(new PropertyChangedEventArgs(property));
}
因此,如果您的原始属性如下所示:
string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
使用 Afterthought 应用上述修改后,它看起来像这样:
string name;
public string Name
{
get
{
return name;
}
set
{
string oldValue = Name;
name = value;
NotificationAmender<ConcreteClass>.OnPropertyChanged<string>(
this, "Name", oldValue, value, Name);
}
}
在您的情况下,在 setter 之后(或之前)调用的静态方法可以命名为您想要的任何名称并执行您想要的任何操作。这只是拦截属性设置器的具体且众所周知的原因的一个示例。鉴于您知道属性是非虚拟的,因此不可能创建代理子类来执行拦截,所以我认为像 Afterthought 或 PostSharp 这样的 AOP 方法是您最好的选择。
此外,使用 Afterthought,您可以实现拦截,使得生成的程序集对 Afterthought 没有任何引用或依赖关系,并且如果您的拦截逻辑实际上没有为您的目标类型添加/更改 API,则没有理由“所有者”具体类的结果会有问题。