Stop inventing bikes.
Use the usual INotifyPropertyChanged hands will not disappear, without any but.
public class Data { public virtual int Value { get; set; } public virtual string Source { get; set; } }
class BindableObject : BindableBase { public new bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) { return base.SetProperty<T>(ref storage, value, propertyName); } }
public class ProxyData : Data, INotifyPropertyChanged { Data _target; BindableObject _notifier; public ProxyData(Data target) { _target = target; _notifier = new BindableObject(); } public override int Value { set { int newValue = 0; if (_notifier.SetProperty(ref newValue, value)) base.Value = newValue; } } public override string Source { set { string newSource = null; if (_notifier.SetProperty(ref newSource, value)) base.Source = newSource; } } public event PropertyChangedEventHandler PropertyChanged { add { _notifier.PropertyChanged += value; } remove { _notifier.PropertyChanged -= value; } } }
data = new ProxyData(new Data()); (data as INotifyPropertyChanged).PropertyChanged += (s, e) => { Console.WriteLine(string.Format("Property {0} changed!", e.PropertyName)); }; data.Value = 10; data.Source = "List";
class NotifyPropertyChangedBehavior : IInterceptionBehavior, INotifyPropertyChanged { static readonly MethodBase _add; static readonly MethodBase _remove; static NotifyPropertyChangedBehavior() { var methods = typeof(INotifyPropertyChanged).GetMethods(); _add = methods[0]; _remove = methods[1]; } public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { IMethodReturn result = null; if (IsPropertyChanged(input)) if (SubscribeUnsubscribe(input)) result = input.CreateMethodReturn(null); else { PropertyInfo property; if (IsSetMethodCalled(out property, input)) result = SetValue(property, input, getNext); } return result ?? getNext()(input, getNext); } public bool WillExecute { get { return true; } } public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// /// </summary> /// <returns></returns> bool IsSetMethodCalled(out PropertyInfo property, IMethodInvocation input) { string propertyName = input.MethodBase.Name.TrimStart("set_".ToArray()); property = input.Target.GetType().GetProperty(propertyName); return property != null; } /// <summary> /// /// </summary> /// <returns></returns> IMethodReturn SetValue(PropertyInfo property, IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var oldValue = property.GetValue(input.Target, new object[0]); var newValue = input.Arguments[0]; IMethodReturn result = null; // if (!Equals(oldValue, newValue)) { result = getNext()(input, getNext); if (PropertyChanged != null) PropertyChanged(input.Target, new PropertyChangedEventArgs(property.Name)); } else result = input.CreateMethodReturn(null); return result; } /// <summary> /// INotifyPropertyChanged /// </summary> bool SubscribeUnsubscribe(IMethodInvocation input) { if (input.MethodBase == _add) { PropertyChanged += (PropertyChangedEventHandler)input.Arguments[0]; return true; } else if (input.MethodBase == _remove) { PropertyChanged -= (PropertyChangedEventHandler)input.Arguments[0]; return true; } return false; } /// <summary> /// INotifyPropertyChanged /// </summary> bool IsPropertyChanged(IMethodInvocation input) { return input.Target is INotifyPropertyChanged; } }
IUnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterType<Data>(new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<NotifyPropertyChangedBehavior>() , new AdditionalInterface<INotifyPropertyChanged>()); var data = container.Resolve<Data>(); (data as INotifyPropertyChanged).PropertyChanged += (s, e) => { Console.WriteLine(string.Format("Property {0} changed!", e.PropertyName)); }; data.Value = 10; data.Source = "List"; data.Value = 10; Console.ReadKey();
public static class Extensions { public static IUnityContainer RegisterViewModel<T>(this IUnityContainer container) where T : class { container.AddNewExtension<Interception>(); return container.RegisterType<T>(new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<NotifyPropertyChangedBehavior>() , new AdditionalInterface<INotifyPropertyChanged>()); } }
container.RegisterViewModel<Data>();
Source: https://habr.com/ru/post/281294/
All Articles