Example #1
0
        public void BasicConstructorLifeCycleTest()
        {
            var listenerSuccess = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher, (sender, e) => listenerSuccess = true);

            //------------------
            listenerSuccess.Is(false);

            publisher.RaisePropertyChanged(string.Empty);

            listenerSuccess.Is(true);

            //------------------
            listenerSuccess = false;

            listener.Dispose();
            publisher.RaisePropertyChanged(string.Empty);

            listenerSuccess.Is(false);

            try
            {
                listener.RegisterHandler((sender, e) => listenerSuccess = true);
            }
            catch (Exception e)
            {
                e.GetType().Is(typeof(ObjectDisposedException));
            }
        }
Example #2
0
        public void WeakEventTest()
        {
            var listener1Success = false;

            var eventPublisher = new TestEventPublisher();

            var listener1 = new PropertyChangedWeakEventListener(eventPublisher, (sender, e) => listener1Success = true);

            var listenerWeakReference = new WeakReference(listener1);

            //------------------
            listener1Success.Is(false);

            eventPublisher.RaisePropertyChanged(null);

            listener1Success.Is(true);

            //------------------
            listener1Success = false;

            listener1 = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            eventPublisher.RaisePropertyChanged(null);

            listener1Success.Is(false);
        }
Example #3
0
        public void SourceReferenceMemoryLeakTest()
        {
            var handler1Called = false;

            var publisherStrongReference = new TestEventPublisher();
            var publisherWeakReference   = new WeakReference <TestEventPublisher>(publisherStrongReference);

            var listener = new PropertyChangedWeakEventListener(publisherStrongReference);

            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; });

            publisherStrongReference.RaisePropertyChanged("Dummy1");

            handler1Called.Is(true);

            listener.Dispose();
            publisherStrongReference = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            TestEventPublisher resultPublisher = null;

            publisherWeakReference.TryGetTarget(out resultPublisher).Is(false);
            resultPublisher.IsNull();
        }
Example #4
0
        public void FilteredHandlerLifeCycleTest()
        {
            var handler1Called = false;
            var handler2Called = false;
            var handler3Called = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; });
            listener.RegisterHandler("Dummy2", (sender, e) => { e.PropertyName.Is("Dummy2"); handler2Called = true; });
            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler3Called = true; });

            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(true);
            handler2Called.Is(true);
            handler3Called.Is(true);

            //------------------
            handler1Called = false;
            handler2Called = false;
            handler3Called = false;

            listener.Dispose();
            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
        }
        public void BasicConstructorLifeCycleTest()
        {
            var listenerSuccess = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher, (sender, e) => listenerSuccess = true);

            //------------------
            listenerSuccess.Is(false);

            publisher.RaisePropertyChanged(string.Empty);

            listenerSuccess.Is(true);

            //------------------
            listenerSuccess = false;

            listener.Dispose();
            publisher.RaisePropertyChanged(string.Empty);

            listenerSuccess.Is(false);

            try
            {
                listener.RegisterHandler((sender, e) => listenerSuccess = true);
            }
            catch (Exception e)
            {
                e.GetType().Is(typeof(ObjectDisposedException));
            }

        }
 public AccountSelectWindow()
 {
     InitializeComponent();
     composite   = new LivetCompositeDisposable();
     ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
     ctxlistener.Add("StartNewAccount", ExpandNewAccount);
     ctxlistener.Add("FinishNewAccount", CollapseNewAccount);
 }
Example #7
0
 public NotificationPage(NotificationViewModel vm)
 {
     InitializeComponent();
     DataContext = vm;
     this.vm     = vm;
     composite   = new LivetCompositeDisposable();
     ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
 }
Example #8
0
 public NotificationPage(NotificationViewModel vm)
 {
     InitializeComponent();
     DataContext = vm;
     this.vm = vm;
     composite = new LivetCompositeDisposable();
     ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
 }
 public AccountSelectWindow()
 {
     InitializeComponent();
     composite = new LivetCompositeDisposable();
     ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
     ctxlistener.Add("StartNewAccount", ExpandNewAccount);
     ctxlistener.Add("FinishNewAccount", CollapseNewAccount);
 }
Example #10
0
        public MainWindow()
        {
            InitializeComponent();

            vm = DataContext as MainWindowViewModel;
            composite = new LivetCompositeDisposable();

            ctxlistener = new PropertyChangedWeakEventListener(vm);
            ctxlistener.Add("AccessTokenRequest", StartAccountSelect);
            ctxlistener.Add("ReplyStart", ExpandNewTweet);
            ctxlistener.Add("ToggleNewStatus", ToggleNewTweet);
            ctxlistener.Add("StatusAction", (s, e) => RequestAction(vm.StatusAction.Type, vm.StatusAction.Information));
            ctxlistener.Add("UserTimeline", (s, e) =>
                AddTab("ユーザー定義タブ1",
                new Frame
            {
                NavigationUIVisibility = NavigationUIVisibility.Hidden,
                Content = new UserCustomizableTimelinePage(vm.UserTimelineViewModel)
            }, vm.UserTimelineViewModel));

            ctxlistener.Add("StatusUpdate", (s, e) =>
            {
                DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
                {
                    if (TabControlMain.SelectedIndex != 0 && setting.MainWindow.NotifyNewStatus)
                    {

                        EmphasisTextBlock(TextBlockTimeline);
                        urs++;
                        TextBlockUnreadStatuses.Text = String.Format(" {0}", urs);

                    }
                }));
            });

            ctxlistener.Add("EventUpdate", (s, e) =>
            {
                DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
                {
                    if (TabControlMain.SelectedIndex != 1 && setting.MainWindow.NotifyNewNotification)
                    {

                        EmphasisTextBlock(TextBlockNotification);
                        urn++;
                        TextBlockUnreadNotifications.Text = String.Format(" {0}", urn);

                    }
                }));
            });

            composite.Add(ctxlistener);

            setting = Kbtter3Extension.LoadJson<Kbtter3Setting>(App.ConfigurationFileName);
            if (!setting.MainWindow.AllowJokeCommands) ToolBarJokes.Visibility = Visibility.Collapsed;

            SetShortcuts();
        }
Example #11
0
        public MainWindow()
        {
            InitializeComponent();

            vm        = DataContext as MainWindowViewModel;
            composite = new LivetCompositeDisposable();

            ctxlistener = new PropertyChangedWeakEventListener(vm);
            ctxlistener.Add("AccessTokenRequest", StartAccountSelect);
            ctxlistener.Add("ReplyStart", ExpandNewTweet);
            ctxlistener.Add("ToggleNewStatus", ToggleNewTweet);
            ctxlistener.Add("StatusAction", (s, e) => RequestAction(vm.StatusAction.Type, vm.StatusAction.Information));
            ctxlistener.Add("UserTimeline", (s, e) =>
                            AddTab("ユーザー定義タブ1",
                                   new Frame
            {
                NavigationUIVisibility = NavigationUIVisibility.Hidden,
                Content = new UserCustomizableTimelinePage(vm.UserTimelineViewModel)
            }, vm.UserTimelineViewModel));

            ctxlistener.Add("StatusUpdate", (s, e) =>
            {
                DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
                {
                    if (TabControlMain.SelectedIndex != 0 && setting.MainWindow.NotifyNewStatus)
                    {
                        EmphasisTextBlock(TextBlockTimeline);
                        urs++;
                        TextBlockUnreadStatuses.Text = String.Format(" {0}", urs);
                    }
                }));
            });

            ctxlistener.Add("EventUpdate", (s, e) =>
            {
                DispatcherHelper.UIDispatcher.BeginInvoke(new Action(() =>
                {
                    if (TabControlMain.SelectedIndex != 1 && setting.MainWindow.NotifyNewNotification)
                    {
                        EmphasisTextBlock(TextBlockNotification);
                        urn++;
                        TextBlockUnreadNotifications.Text = String.Format(" {0}", urn);
                    }
                }));
            });

            composite.Add(ctxlistener);

            setting = Kbtter3Extension.LoadJson <Kbtter3Setting>(App.ConfigurationFileName);
            if (!setting.MainWindow.AllowJokeCommands)
            {
                ToolBarJokes.Visibility = Visibility.Collapsed;
            }

            SetShortcuts();
        }
Example #12
0
            public HandlerMemoryLeakTestClass(INotifyPropertyChanged publisher)
            {
                Listener = new PropertyChangedWeakEventListener(publisher);

                // This handler refers "this".
                PropertyChangedEventHandler handler = (sender, e) => { ToString(); };

                Listener.RegisterHandler(handler);
                Listener.RegisterHandler("Dummy1", handler);
            }
Example #13
0
        public StatusPage(StatusViewModel vm)
        {
            statvm = vm;
            DataContext = vm;
            InitializeComponent();
            elm = vm.TextElements;
            stsn = vm.ScreenName;

            if (vm.Via == "") StackPanelBlockVia.Visibility = Visibility.Collapsed;
            SetMainText();

            composite = new LivetCompositeDisposable();
            ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
            ctxlistener.Add("Delete", DeleteContent);
        }
        public void MultipleHandlerLifeCycleTest()
        {
            var handler1Success = false;
            var handler2Success = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            //------------------
            handler1Success.Is(false);
            handler2Success.Is(false);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(false);
            handler2Success.Is(false);

            //------------------
            listener.RegisterHandler((sender, e) => handler1Success = true);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(true);
            handler2Success.Is(false);

            //------------------
            handler1Success = false;
            handler2Success = false;

            listener.RegisterHandler((sender, e) => handler2Success = true);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(true);
            handler2Success.Is(true);

            //------------------
            handler1Success = false;
            handler2Success = false;

            listener.Dispose();
            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(false);
            handler2Success.Is(false);
        }
Example #15
0
        public void MultipleHandlerLifeCycleTest()
        {
            var handler1Success = false;
            var handler2Success = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            //------------------
            handler1Success.Is(false);
            handler2Success.Is(false);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(false);
            handler2Success.Is(false);

            //------------------
            listener.RegisterHandler((sender, e) => handler1Success = true);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(true);
            handler2Success.Is(false);

            //------------------
            handler1Success = false;
            handler2Success = false;

            listener.RegisterHandler((sender, e) => handler2Success = true);

            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(true);
            handler2Success.Is(true);

            //------------------
            handler1Success = false;
            handler2Success = false;

            listener.Dispose();
            publisher.RaisePropertyChanged(string.Empty);

            handler1Success.Is(false);
            handler2Success.Is(false);
        }
Example #16
0
        public StatusPage(StatusViewModel vm)
        {
            statvm      = vm;
            DataContext = vm;
            InitializeComponent();
            elm  = vm.TextElements;
            stsn = vm.ScreenName;

            if (vm.Via == "")
            {
                StackPanelBlockVia.Visibility = Visibility.Collapsed;
            }
            SetMainText();

            composite   = new LivetCompositeDisposable();
            ctxlistener = new PropertyChangedWeakEventListener((INotifyPropertyChanged)DataContext);
            ctxlistener.Add("Delete", DeleteContent);
        }
Example #17
0
        public void MultiThreadHandlerTest()
        {
            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            var handlerCalledCount = 0;

            var parentTask = new Task(() =>
            {
                var tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.AttachedToParent);

                for (int i = 0; i < 50; i++)
                {
                    tf.StartNew(() =>
                    {
                        for (int f = 0; f < 500; f++)
                        {
                            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handlerCalledCount++; });
                        }
                    });
                }
            });

            parentTask.Start();
            parentTask.Wait();

            handlerCalledCount.Is(0);

            publisher.RaisePropertyChanged("Dummy1");

            handlerCalledCount.Is(25000);

            handlerCalledCount = 0;

            listener.Dispose();
            publisher.RaisePropertyChanged("Dummy1");

            handlerCalledCount.Is(0);
        }
Example #18
0
        /// <summary>
        /// <see cref="ChangeValueWhenModelPropertyChangeAttribute"/> が指定されたプロパティの変更通知を有効化します。
        /// </summary>
        protected void EnableAutoPropertyChangedEvent(INotifyPropertyChanged model)
        {
            PropertyChangedWeakEventListener listener = null;

            foreach (var prop in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                PropertyChangedEventHandler handler = null;
                foreach (var attr in prop.GetCustomAttributes <ChangeValueWhenModelPropertyChangeAttribute>())
                {
                    if (attr.DependentPropertyNames == null)
                    {
                        continue;
                    }

                    foreach (var propName in attr.DependentPropertyNames)
                    {
                        if (listener == null)
                        {
                            listener = new PropertyChangedWeakEventListener(model);
                        }
                        if (handler == null)
                        {
                            handler = CreateHandler(prop.Name);
                        }

                        listener.Add(propName, handler);
                    }
                }
            }

            if (listener != null)
            {
                this.CompositeDisposable.Add(listener);
            }

            PropertyChangedEventHandler CreateHandler(string propertyName) => (_, __) => this.RaisePropertyChanged(propertyName);
        }
        public void SourceReferenceMemoryLeakTest()
        {
            var handler1Called = false;

            var publisherStrongReference = new TestEventPublisher();
            var publisherWeakReference = new WeakReference<TestEventPublisher>(publisherStrongReference);

            var listener = new PropertyChangedWeakEventListener(publisherStrongReference);
            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; });

            publisherStrongReference.RaisePropertyChanged("Dummy1");

            handler1Called.Is(true);

            listener.Dispose();
            publisherStrongReference = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            TestEventPublisher resultPublisher = null;
            publisherWeakReference.TryGetTarget(out resultPublisher).Is(false);
            resultPublisher.IsNull();
        }
        public void FilteredHandlerLifeCycleTest()
        {
            var handler1Called = false;
            var handler2Called = false;
            var handler3Called = false;

            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; });
            listener.RegisterHandler("Dummy2", (sender, e) => { e.PropertyName.Is("Dummy2"); handler2Called = true; });
            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler3Called = true; });

            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(true);
            handler2Called.Is(true);
            handler3Called.Is(true);

            //------------------
            handler1Called = false;
            handler2Called = false;
            handler3Called = false;

            listener.Dispose();
            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
        }
        public void AddHandlerKindTest()
        {
            var handler1Called = false;
            var handler2Called = false;
            var handler3Called = false;
            var handler4Called = false;
            var handler5Called = false;

            var publisher = new TestEventPublisher();
            var listener1 = new PropertyChangedWeakEventListener(publisher)
            {
                {"Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; }},
                {() => publisher.Dummy2,
                        (sender, e) => { e.PropertyName.Is("Dummy2"); handler2Called = true;},
                        (sender, e) => { e.PropertyName.Is("Dummy2"); handler3Called = true;}
                },
                (sender,e) => handler4Called = true,
                {"Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler5Called = true; }}
            };

            publisher.RaisePropertyChanged(null);

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(true);
            handler5Called.Is(false);

            handler4Called = false;

            publisher.RaisePropertyChanged("Dummy1");

            handler1Called.Is(true);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(true);
            handler5Called.Is(true);

            handler1Called = false;
            handler4Called = false;
            handler5Called = false;

            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(true);
            handler3Called.Is(true);
            handler4Called.Is(true);
            handler5Called.Is(false);

            handler1Called = false;
            handler2Called = false;
            handler3Called = false;
            handler4Called = false;
            handler5Called = false;

            listener1.Dispose();

            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(false);
            handler5Called.Is(false);
        }
        public void MultiThreadHandlerTest()
        {
            var publisher = new TestEventPublisher();

            var listener = new PropertyChangedWeakEventListener(publisher);

            var handlerCalledCount = 0;

            var parentTask = new Task(() =>
            {
                var tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.AttachedToParent);

                for (int i = 0; i < 50; i++)
                {
                    tf.StartNew(() =>
                    {
                        for (int f = 0; f < 500; f++)
                        {
                            listener.RegisterHandler("Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handlerCalledCount++; });
                        }

                    });
                }
            });

            parentTask.Start();
            parentTask.Wait();

            handlerCalledCount.Is(0);

            publisher.RaisePropertyChanged("Dummy1");

            handlerCalledCount.Is(25000);

            handlerCalledCount = 0;

            listener.Dispose();
            publisher.RaisePropertyChanged("Dummy1");

            handlerCalledCount.Is(0);
        }
Example #23
0
        public void AddHandlerKindTest()
        {
            var handler1Called = false;
            var handler2Called = false;
            var handler3Called = false;
            var handler4Called = false;
            var handler5Called = false;

            var publisher = new TestEventPublisher();
            var listener1 = new PropertyChangedWeakEventListener(publisher)
            {
                { "Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler1Called = true; } },
                { () => publisher.Dummy2,
                  (sender, e) => { e.PropertyName.Is("Dummy2"); handler2Called = true; },
                  (sender, e) => { e.PropertyName.Is("Dummy2"); handler3Called = true; } },
                (sender, e) => handler4Called = true,
                { "Dummy1", (sender, e) => { e.PropertyName.Is("Dummy1"); handler5Called = true; } }
            };

            publisher.RaisePropertyChanged(null);

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(true);
            handler5Called.Is(false);

            handler4Called = false;

            publisher.RaisePropertyChanged("Dummy1");

            handler1Called.Is(true);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(true);
            handler5Called.Is(true);

            handler1Called = false;
            handler4Called = false;
            handler5Called = false;

            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(true);
            handler3Called.Is(true);
            handler4Called.Is(true);
            handler5Called.Is(false);

            handler1Called = false;
            handler2Called = false;
            handler3Called = false;
            handler4Called = false;
            handler5Called = false;

            listener1.Dispose();

            publisher.RaisePropertyChanged("Dummy1");
            publisher.RaisePropertyChanged("Dummy2");

            handler1Called.Is(false);
            handler2Called.Is(false);
            handler3Called.Is(false);
            handler4Called.Is(false);
            handler5Called.Is(false);
        }
            public HandlerMemoryLeakTestClass(INotifyPropertyChanged publisher)
            {
                Listener = new PropertyChangedWeakEventListener(publisher);

                // This handler refers "this".
                PropertyChangedEventHandler handler = (sender, e) => { ToString(); };
                Listener.RegisterHandler(handler);
                Listener.RegisterHandler("Dummy1", handler);
            }
Example #25
0
        /// <summary>
        /// <see cref="ChangeCanExecuteWhenModelPropertyChangeAttribute"/> および <see cref="ChangeCanExecuteWhenThisPropertyChangeAttribute"/> が指定されたコマンドの <see cref="System.Windows.Input.ICommand.CanExecuteChanged"/> を自動的に発生させるようにします。
        /// </summary>
        protected void EnableAutoCanExecuteChangedEvent(INotifyPropertyChanged model = null)
        {
            PropertyChangedEventListener     thisListener  = null;
            PropertyChangedWeakEventListener modelListener = null;

            foreach (var prop in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                PropertyChangedEventHandler handler = null;

                foreach (var attr in prop.GetCustomAttributes())
                {
                    if (attr is ChangeCanExecuteWhenThisPropertyChangeAttribute thisAttr)
                    {
                        if (thisAttr.DependentPropertyNames == null)
                        {
                            continue;
                        }

                        foreach (var propName in thisAttr.DependentPropertyNames)
                        {
                            if (thisListener == null)
                            {
                                thisListener = new PropertyChangedEventListener(this);
                            }
                            if (handler == null)
                            {
                                handler = CreateHandler(prop);
                            }

                            thisListener.Add(propName, handler);
                        }
                    }
                    else if (attr is ChangeCanExecuteWhenModelPropertyChangeAttribute modelAttr)
                    {
                        if (modelAttr.DependentPropertyNames == null)
                        {
                            continue;
                        }

                        if (model == null)
                        {
                            throw new ArgumentNullException(nameof(ChangeCanExecuteWhenModelPropertyChangeAttribute)
                                                            + " が指定されたプロパティが存在するにもかかわらず " + nameof(model) + " が null です。");
                        }

                        foreach (var propName in modelAttr.DependentPropertyNames)
                        {
                            if (modelListener == null)
                            {
                                modelListener = new PropertyChangedWeakEventListener(model);
                            }
                            if (handler == null)
                            {
                                handler = CreateHandler(prop);
                            }

                            modelListener.Add(propName, handler);
                        }
                    }
                }
            }

            if (thisListener != null)
            {
                this.CompositeDisposable.Add(thisListener);
            }
            if (modelListener != null)
            {
                this.CompositeDisposable.Add(modelListener);
            }

            PropertyChangedEventHandler CreateHandler(PropertyInfo prop) =>
            Expression.Lambda <PropertyChangedEventHandler>(
                Expression.Call(
                    Expression.Property(Expression.Constant(this), prop),
                    s_viewModelCommandRaiseCanExecuteChangedMethodInfo
                    ),
                Expression.Parameter(typeof(object)),
                Expression.Parameter(typeof(PropertyChangedEventArgs))
                ).Compile();
        }
        public void WeakEventTest()
        {
            var listener1Success = false;

            var eventPublisher = new TestEventPublisher();

            var listener1 = new PropertyChangedWeakEventListener(eventPublisher, (sender, e) => listener1Success = true);

            var listenerWeakReference = new WeakReference(listener1);

            //------------------
            listener1Success.Is(false);

            eventPublisher.RaisePropertyChanged(null);

            listener1Success.Is(true);

            //------------------
            listener1Success = false;

            listener1 = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            eventPublisher.RaisePropertyChanged(null);

            listener1Success.Is(false);
        }