From b488ca179a0b72aa074c24d7948fe78f380af69a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 23 Jun 2018 13:32:05 +0200 Subject: [PATCH] Use custom class for direct binding subscriptions. --- src/Avalonia.Base/AvaloniaObject.cs | 53 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 48e72db126..baca1494be 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -10,6 +10,7 @@ using System.Reactive.Linq; using Avalonia.Data; using Avalonia.Diagnostics; using Avalonia.Logging; +using Avalonia.Reactive; using Avalonia.Threading; using Avalonia.Utilities; @@ -38,7 +39,7 @@ namespace Avalonia /// Maintains a list of direct property binding subscriptions so that the binding source /// doesn't get collected. /// - private List _directBindings; + private List _directBindings; /// /// Event handler for implementation. @@ -359,25 +360,12 @@ namespace Avalonia property, description); - IDisposable subscription = null; - if (_directBindings == null) { - _directBindings = new List(); + _directBindings = new List(); } - subscription = source - .Select(x => CastOrDefault(x, property.PropertyType)) - .Do(_ => { }, () => _directBindings.Remove(subscription)) - .Subscribe(x => SetDirectValue(property, x)); - - _directBindings.Add(subscription); - - return Disposable.Create(() => - { - subscription.Dispose(); - _directBindings.Remove(subscription); - }); + return new DirectBindingSubscription(this, property, source); } else { @@ -908,5 +896,38 @@ namespace Avalonia value, priority); } + + private class DirectBindingSubscription : IObserver, IDisposable + { + readonly AvaloniaObject _owner; + readonly AvaloniaProperty _property; + IDisposable _subscription; + + public DirectBindingSubscription( + AvaloniaObject owner, + AvaloniaProperty property, + IObservable source) + { + _owner = owner; + _property = property; + _owner._directBindings.Add(this); + _subscription = source.Subscribe(this); + } + + public void Dispose() + { + _subscription.Dispose(); + _owner._directBindings.Remove(this); + } + + public void OnCompleted() => Dispose(); + public void OnError(Exception error) => Dispose(); + + public void OnNext(object value) + { + var castValue = CastOrDefault(value, _property.PropertyType); + _owner.SetDirectValue(_property, castValue); + } + } } }