【发布时间】:2023-03-29 09:25:01
【问题描述】:
我是 .NET 和 WPF 的新手,所以我希望我能正确地提出这个问题。 我正在使用使用 PostSharp 1.5 实现的 INotifyPropertyChanged:
[Serializable, DebuggerNonUserCode, AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = false),
MulticastAttributeUsage(MulticastTargets.Class, AllowMultiple = false, Inheritance = MulticastInheritance.None, AllowExternalAssemblies = true)]
public sealed class NotifyPropertyChangedAttribute : CompoundAspect
{
public int AspectPriority { get; set; }
public override void ProvideAspects(object element, LaosReflectionAspectCollection collection)
{
Type targetType = (Type)element;
collection.AddAspect(targetType, new PropertyChangedAspect { AspectPriority = AspectPriority });
foreach (var info in targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(pi => pi.GetSetMethod() != null))
{
collection.AddAspect(info.GetSetMethod(), new NotifyPropertyChangedAspect(info.Name) { AspectPriority = AspectPriority });
}
}
}
[Serializable]
internal sealed class PropertyChangedAspect : CompositionAspect
{
public override object CreateImplementationObject(InstanceBoundLaosEventArgs eventArgs)
{
return new PropertyChangedImpl(eventArgs.Instance);
}
public override Type GetPublicInterface(Type containerType)
{
return typeof(INotifyPropertyChanged);
}
public override CompositionAspectOptions GetOptions()
{
return CompositionAspectOptions.GenerateImplementationAccessor;
}
}
[Serializable]
internal sealed class NotifyPropertyChangedAspect : OnMethodBoundaryAspect
{
private readonly string _propertyName;
public NotifyPropertyChangedAspect(string propertyName)
{
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName");
_propertyName = propertyName;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
var targetType = eventArgs.Instance.GetType();
var setSetMethod = targetType.GetProperty(_propertyName);
if (setSetMethod == null) throw new AccessViolationException();
var oldValue = setSetMethod.GetValue(eventArgs.Instance, null);
var newValue = eventArgs.GetReadOnlyArgumentArray()[0];
if (oldValue == newValue) eventArgs.FlowBehavior = FlowBehavior.Return;
}
public override void OnSuccess(MethodExecutionEventArgs eventArgs)
{
var instance = eventArgs.Instance as IComposed<INotifyPropertyChanged>;
var imp = instance.GetImplementation(eventArgs.InstanceCredentials) as PropertyChangedImpl;
imp.OnPropertyChanged(_propertyName);
}
}
[Serializable]
internal sealed class PropertyChangedImpl : INotifyPropertyChanged
{
private readonly object _instance;
public PropertyChangedImpl(object instance)
{
if (instance == null) throw new ArgumentNullException("instance");
_instance = instance;
}
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(string propertyName)
{
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName");
var handler = PropertyChanged as PropertyChangedEventHandler;
if (handler != null) handler(_instance, new PropertyChangedEventArgs(propertyName));
}
}
}
然后我有几个实现 [NotifyPropertyChanged] 的类(用户和地址)。 它工作正常。但我想要的是,如果子对象发生变化(在我的示例地址中),父对象会得到通知(在我的情况下是用户)。是否可以扩展此代码,使其自动在父对象上创建侦听器,以侦听其子对象的变化?
【问题讨论】:
-
您希望孩子听众做什么?
-
实际上在这一点上我想要的是父母得到通知(关于孩子的任何变化 - 任何深度)。
-
这是一个更具挑战性的问题。您必须使用某种反思(如果您不能依靠您的孩子来通知您有关他们孩子的变化),并且在反思期间决定如何以及何时递归总是有点冒险。是什么促使您找到这个解决方案?可能会有一些设计更改有助于简化您的任务。
-
附带说明,如果这篇文章可以标记为 PostSharp,那就太好了。该工具的创建者阅读了这些板,并且能够比我更好地回答您关于 v1.5 的问题。
-
我确实用 PostSharp 标签标记了这个,我还在 PostSharp 论坛上发帖......现在我正在等待一个 anwser.... 让它工作将是一件大事。放弃所有 NPC 编码并保持课堂清洁是我的梦想成真!
标签: c# wpf inotifypropertychanged postsharp