private void UnHookNotifyChildPropertyChangedHandler(NotifyChildPropertyChangedEventHandlerDescriptor handlerDescriptor)
        {
            object currentValue = handlerDescriptor.Reference.Target;

            if (currentValue != null)
            {
                NotifyPropertyChangedAccessor.RemoveChildPropertyChangedHandler(currentValue, handlerDescriptor.Handler);
            }
        }
        private void HookNotifyChildPropertyChangedHandler(object instance, string locationName)
        {
            object currentValue = instance as INotifyPropertyChanged;

            if (currentValue != null &&
                instrumentedTypes.GetOrAdd(currentValue.GetType(), type => type.IsDefined(typeof(NotifyPropertyChangedAttribute), true)))
            {
                string locationNameClosure = locationName;
                NotifyChildPropertyChangedEventHandlerDescriptor handlerDescriptor = new NotifyChildPropertyChangedEventHandlerDescriptor(
                    currentValue, (_, a) => this.NotifyChildPropertyChangedEventHandler(locationNameClosure, a));
                this.notifyChildPropertyChangedHandlers.AddOrUpdate(locationNameClosure, handlerDescriptor);
                NotifyPropertyChangedAccessor.AddChildPropertyChangedHandler(currentValue, handlerDescriptor.Handler);
            }
        }
        private static void RaisePropertyChangesInternal(
            ChangedPropertiesAccumulator accumulator, bool raiseChildPropertyChanges, Func <WeakPropertyDescriptor, bool> propertySelectorPredicate)
        {
            areEventsFiring = true;
            accumulator.Compact();

            List <WeakPropertyDescriptor> objectsToRaisePropertyChanged;

            int loopCount = 0;

            Dictionary <WeakPropertyDescriptor, int> raiseCounts = accumulator.ToDictionary(w => w, w => 0);

            do
            {
                objectsToRaisePropertyChanged = accumulator.Where(propertySelectorPredicate).ToList();

                foreach (WeakPropertyDescriptor w in objectsToRaisePropertyChanged)
                {
                    int raiseCount = raiseCounts.GetOrCreate(w, () => 0);

                    //INPC handler may raise INPC again and process some of our events;
                    //we're working on accumulator copy, so only way to know it is to have a flag on the descriptor

                    if (w.Processed || raiseChildPropertyChanges ? raiseCount > 0 : raiseCount > 1)
                    {
                        w.Processed = true;
                        continue;
                    }

                    w.Processed = true;
                    accumulator.Remove(w);
                    object cpc = w.Instance.Target;

                    if (cpc != null)   //Target may not be alive any more
                    {
                        raiseCounts[w]++;

                        if (raiseChildPropertyChanges)
                        {
                            NotifyPropertyChangedAccessor.RaiseChildPropertyChanged(cpc, w.PropertyPath);
                        }
                        else
                        {
                            NotifyPropertyChangedAccessor.RaisePropertyChanged(cpc, w.PropertyPath);
                        }
                    }
                }
                //Notifications may cause generation of new notifications, continue until there is nothing left to raise
            }while (objectsToRaisePropertyChanged.Count > 0 && ++loopCount <= 32);

            areEventsFiring = false;

            //TODO: Verify the loop above will always stop.
            //If there's a risk it won't, call RaiseChildPropertyChanged from NPCAttribute.ChildPropertyChangedEventHandler to bubble up CNPC notifications
            //(this may lead to a lot of unneccessary recursion, however, and a lot of continuations on w.Processed check above)

            // if we encounter infinite loop generate meaningful exception for bug report.
            if (loopCount == 32)
            {
                throw new NotifyPropertyChangedAlgorithmInfiniteLoop("Encountered infinite loop while raising PropertyChanged events");
            }
        }
 public void HookPropertyChangedHandler()
 {
     NotifyPropertyChangedAccessor.AddPropertyChangedHandler(this.instance, this.OnPropertyChanged);
 }