Exemplo n.º 1
0
        /// <summary>
        /// Return a <see cref="ManagedWeakReference"/> to the pool.
        /// </summary>
        /// <param name="owner">The instance returning the reference to the pool.</param>
        /// <param name="managedWeakReference">A <see cref="ManagedWeakReference"/> to return</param>
        /// <remarks>
        /// The returned <see cref="ManagedWeakReference"/> may not be owner by the <paramref name="owner"/>,
        /// in which case, the <paramref name="managedWeakReference"/> will not be returned to the pool. If the reference
        /// if an <see cref="IWeakReferenceProvider"/> it is not returned as well.
        /// A null <paramref name="managedWeakReference"/> is ignored.
        /// </remarks>
        public static void ReturnWeakReference(object owner, ManagedWeakReference managedWeakReference)
        {
            if (Enabled &&
                managedWeakReference != null &&
                managedWeakReference.Owner == owner &&
                !managedWeakReference.IsSelfReference
                )
            {
                lock (_gate)
                {
                    if (_weakReferencePool.Count < MaxReferences)
                    {
                        ReturnUnsafeWeakReference(managedWeakReference.GetUnsafeTargetHandle());

                        if (!(managedWeakReference.Owner is IWeakReferenceProvider))
                        {
                            // The owner's weak reference may have been borrowed from an IWeakReferenceProvider instance
                            // We're not release it if it's the case.
                            ReturnUnsafeWeakReference(managedWeakReference.GetUnsafeOwnerHandle());
                        }

                        managedWeakReference.Dispose();
                    }
                }
            }
        }
Exemplo n.º 2
0
        internal void SetWeakDataContext(ManagedWeakReference weakDataContext)
        {
            if (!_disposed)
            {
                var previousStorage = _dataContextWeakStorage;

                _dataContextWeakStorage = weakDataContext;
                OnDataContextChanged();

                // Return the reference to the pool after it's been released from the underlying BindingItem instances.
                // Failing to do so makes the reference change without the bindings knowing about it,
                // making the reference comparison always equal.
                Uno.UI.DataBinding.WeakReferencePool.ReturnWeakReference(this, previousStorage);
            }
        }
Exemplo n.º 3
0
            internal void SetWeakDataContext(ManagedWeakReference weakDataContext, bool transferReferenceOwnership = false)
            {
                if (!_disposed && DependencyObjectStore.AreDifferent(DataContext, weakDataContext?.Target))
                {
                    var previousStorage = _dataContextWeakStorage;

                    _dataContextWeakStorage = weakDataContext;
                    OnDataContextChanged();

                    // Return the reference to the pool after it's been released from the next BindingItem instances.
                    // Failing to do so makes the reference change without the bindings knowing about it,
                    // making the reference comparison always equal.
                    Uno.UI.DataBinding.WeakReferencePool.ReturnWeakReference(this, previousStorage);
                }
            }
Exemplo n.º 4
0
        /// <summary>
        /// Subscibes for updates to the INotifyPropertyChanged interface.
        /// </summary>
        private static IDisposable SubscribeToNotifyPropertyChanged(ManagedWeakReference dataContextReference, string propertyName, Action newValueAction)
        {
            // Attach to the Notify property changed events
            var notify = dataContextReference.Target as INotifyPropertyChanged;

            if (notify != null)
            {
                if (propertyName.Length != 0 && propertyName[0] == '[')
                {
                    propertyName = "Item" + propertyName;
                }

                var newValueActionWeak = Uno.UI.DataBinding.WeakReferencePool.RentWeakReference(null, newValueAction);

                PropertyChangedEventHandler handler = (s, args) =>
                {
                    if (args.PropertyName == propertyName)
                    {
                        if (typeof(BindingPath).Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                        {
                            typeof(BindingPath).Log().Debug("Property changed for {0} on [{1}]".InvariantCultureFormat(propertyName, dataContextReference.Target?.GetType()));
                        }

                        (newValueActionWeak.Target as Action)?.Invoke();
                    }
                };

                notify.PropertyChanged += handler;

                return(Disposable.Create(() =>
                {
                    // This weak reference ensure that the closure will not link
                    // the caller and the callee, in the same way "newValueActionWeak"
                    // does not link the callee to the caller.
                    var that = dataContextReference.Target as INotifyPropertyChanged;

                    if (that != null)
                    {
                        that.PropertyChanged -= handler;
                    }

                    Uno.UI.DataBinding.WeakReferencePool.ReturnWeakReference(null, newValueActionWeak);
                }));
            }

            return(null);
        }