由于这是一个非常常见的问题,也是选择 Miguel 建议的 AOP 方法的重要理由,我 created an example 为 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,则没有理由“具体类的“所有者”会对结果产生问题。