.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] を実装するクラス (ユーザーとアドレス) がいくつかあります。それは正常に動作します。しかし、私が望むのは、子オブジェクトが(私の例のアドレスで)変更された場合、親オブジェクトが通知されることです(私の場合はユーザー)。このコードを拡張して、子オブジェクトの変更をリッスンする親オブジェクトにリスナーを自動的に作成することは可能でしょうか?