Browse Source

Don't produce value when reading (Has)Value.

refactor/style-priorities
Steven Kirk 4 years ago
parent
commit
1e4577fa3f
  1. 37
      src/Avalonia.Base/PropertyStore/BindingEntry.cs
  2. 51
      src/Avalonia.Base/PropertyStore/BindingEntry`1.cs
  3. 33
      src/Avalonia.Base/PropertyStore/UntypedBindingEntry.cs

37
src/Avalonia.Base/PropertyStore/BindingEntry.cs

@ -29,7 +29,7 @@ namespace Avalonia.PropertyStore
{
get
{
StartIfNecessary();
Start(produceValue: false);
return _hasValue;
}
}
@ -44,7 +44,7 @@ namespace Avalonia.PropertyStore
public object? GetValue()
{
StartIfNecessary();
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The binding entry has no value.");
return _value!;
@ -52,21 +52,12 @@ namespace Avalonia.PropertyStore
public bool TryGetValue(out object? value)
{
StartIfNecessary();
Start(produceValue: false);
value = _value;
return _hasValue;
}
public void Start()
{
Debug.Assert(_subscription is null);
// Subscription won't be set until Subscribe completes, but in the meantime we
// need to signal that we've started as Subscribe may cause a value to be produced.
_subscription = Disposable.Empty;
_subscription = _source.Subscribe(this);
}
public void Start() => Start(true);
public void OnCompleted() => BindingCompleted();
public void OnError(Exception error) => BindingCompleted();
@ -84,7 +75,9 @@ namespace Avalonia.PropertyStore
{
_hasValue = false;
_value = default;
_frame.Owner?.OnBindingValueCleared(Property, _frame.Priority);
if (_subscription is not null)
_frame.Owner?.OnBindingValueCleared(Property, _frame.Priority);
}
}
@ -112,7 +105,9 @@ namespace Avalonia.PropertyStore
{
_value = typedValue;
_hasValue = true;
_frame.Owner?.OnBindingValueChanged(Property, _frame.Priority, typedValue);
if (_subscription is not null)
_frame.Owner?.OnBindingValueChanged(Property, _frame.Priority, typedValue);
}
}
else
@ -128,10 +123,16 @@ namespace Avalonia.PropertyStore
_frame.OnBindingCompleted(this);
}
private void StartIfNecessary()
private void Start(bool produceValue)
{
if (_subscription is null)
Start();
if (_subscription is not null)
return;
// Will only produce a new value when subscription isn't null.
if (produceValue)
_subscription = Disposable.Empty;
_subscription = _source.Subscribe(this);
}
}
}

51
src/Avalonia.Base/PropertyStore/BindingEntry`1.cs

@ -42,7 +42,7 @@ namespace Avalonia.PropertyStore
{
get
{
StartIfNecessary();
Start(produceValue: false);
return _hasValue;
}
}
@ -58,31 +58,17 @@ namespace Avalonia.PropertyStore
public T GetValue()
{
StartIfNecessary();
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The binding entry has no value.");
return _value!;
}
public void Start()
{
Debug.Assert(_subscription is null);
// Subscription won't be set until Subscribe completes, but in the meantime we
// need to signal that we've started as Subscribe may cause a value to be produced.
_subscription = Disposable.Empty;
if (_source is IObservable<BindingValue<T>> bv)
_subscription = bv.Subscribe(this);
else if (_source is IObservable<T> b)
_subscription = b.Subscribe(this);
else
throw new AvaloniaInternalException("Unexpected binding source.");
}
public void Start() => Start(true);
public bool TryGetValue([MaybeNullWhen(false)] out T value)
{
StartIfNecessary();
Start(produceValue: false);
value = _value;
return _hasValue;
}
@ -111,7 +97,7 @@ namespace Avalonia.PropertyStore
object? IValueEntry.GetValue()
{
StartIfNecessary();
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The BindingEntry<T> has no value.");
return _value!;
@ -119,7 +105,7 @@ namespace Avalonia.PropertyStore
bool IValueEntry.TryGetValue(out object? value)
{
StartIfNecessary();
Start(produceValue: false);
value = _value;
return _hasValue;
}
@ -130,7 +116,8 @@ namespace Avalonia.PropertyStore
{
_hasValue = false;
_value = default;
_frame.Owner?.OnBindingValueCleared(Property, _frame.Priority);
if (_subscription is not null)
_frame.Owner?.OnBindingValueCleared(Property, _frame.Priority);
}
}
@ -145,10 +132,11 @@ namespace Avalonia.PropertyStore
{
_value = value;
_hasValue = true;
_frame.Owner?.OnBindingValueChanged(Property, _frame.Priority, value);
if (_subscription is not null)
_frame.Owner?.OnBindingValueChanged(Property, _frame.Priority, value);
}
}
else
else if (_subscription is not null)
{
_frame.Owner?.OnBindingValueCleared(Property, _frame.Priority);
}
@ -160,10 +148,21 @@ namespace Avalonia.PropertyStore
_frame.OnBindingCompleted(this);
}
private void StartIfNecessary()
private void Start(bool produceValue)
{
if (_subscription is null)
Start();
if (_subscription is not null)
return;
// Will only produce a new value when subscription isn't null.
if (produceValue)
_subscription = Disposable.Empty;
_subscription = _source switch
{
IObservable<BindingValue<T>> bv => bv.Subscribe(this),
IObservable<T> b => b.Subscribe(this),
_ => throw new AvaloniaInternalException("Unexpected binding source."),
};
}
}
}

33
src/Avalonia.Base/PropertyStore/UntypedBindingEntry.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reactive.Disposables;
using Avalonia.Data;
@ -31,7 +30,7 @@ namespace Avalonia.PropertyStore
{
get
{
StartIfNecessary();
Start(produceValue: false);
return _hasValue;
}
}
@ -47,25 +46,17 @@ namespace Avalonia.PropertyStore
public T GetValue()
{
StartIfNecessary();
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The binding entry has no value.");
return _value!;
}
public void Start()
{
Debug.Assert(_subscription is null);
// Subscription won't be set until Subscribe completes, but in the meantime we
// need to signal that we've started as Subscribe may cause a value to be produced.
_subscription = Disposable.Empty;
_subscription = _source.Subscribe(this);
}
public void Start() => Start(true);
public bool TryGetValue([MaybeNullWhen(false)] out T value)
{
StartIfNecessary();
Start(produceValue: false);
value = _value;
return _hasValue;
}
@ -91,7 +82,7 @@ namespace Avalonia.PropertyStore
object? IValueEntry.GetValue()
{
StartIfNecessary();
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The BindingEntry<T> has no value.");
return _value!;
@ -99,7 +90,7 @@ namespace Avalonia.PropertyStore
bool IValueEntry.TryGetValue(out object? value)
{
StartIfNecessary();
Start(produceValue: false);
value = _value;
return _hasValue;
}
@ -154,10 +145,16 @@ namespace Avalonia.PropertyStore
_frame.OnBindingCompleted(this);
}
private void StartIfNecessary()
private void Start(bool produceValue)
{
if (_subscription is null)
Start();
if (_subscription is not null)
return;
// Will only produce a new value when subscription isn't null.
if (produceValue)
_subscription = Disposable.Empty;
_subscription = _source.Subscribe(this);
}
}
}

Loading…
Cancel
Save