Browse Source

Fix bug in ExpressionObserver.

Ensure `rootGetter` is evaluated each time the observer is initialized; plus failing and now passing test.
pull/8600/head
Steven Kirk 4 years ago
parent
commit
b5891a2ead
  1. 9
      src/Avalonia.Base/Data/Core/ExpressionObserver.cs
  2. 27
      tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs

9
src/Avalonia.Base/Data/Core/ExpressionObserver.cs

@ -52,6 +52,7 @@ namespace Avalonia.Data.Core
private static readonly object UninitializedValue = new object();
private readonly ExpressionNode _node;
private object? _root;
private Func<object?>? _rootGetter;
private IDisposable? _rootSubscription;
private WeakReference<object?>? _value;
private IReadOnlyList<ITransformNode>? _transformNodes;
@ -109,11 +110,9 @@ namespace Avalonia.Data.Core
IObservable<Unit> update,
string? description)
{
_ = rootGetter ?? throw new ArgumentNullException(nameof(rootGetter));
Description = description;
_node = node ?? throw new ArgumentNullException(nameof(rootGetter));
_node.Target = new WeakReference<object?>(rootGetter());
_rootGetter = rootGetter ?? throw new ArgumentNullException(nameof(rootGetter));
_node = node ?? throw new ArgumentNullException(nameof(node));
_root = update.Select(x => rootGetter());
}
@ -263,6 +262,8 @@ namespace Avalonia.Data.Core
protected override void Initialize()
{
_value = null;
if (_rootGetter is not null)
_node.Target = new WeakReference<object?>(_rootGetter());
_node.Subscribe(ValueChanged);
StartRoot();
}

27
tests/Avalonia.Base.UnitTests/Data/Core/ExpressionObserverTests_Property.cs

@ -3,14 +3,13 @@ using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Microsoft.Reactive.Testing;
using System.Threading.Tasks;
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.Threading;
using Avalonia.UnitTests;
using Microsoft.Reactive.Testing;
using Xunit;
using System.Threading.Tasks;
using Avalonia.Markup.Parsers;
using Avalonia.Threading;
namespace Avalonia.Base.UnitTests.Data.Core
{
@ -636,7 +635,25 @@ namespace Avalonia.Base.UnitTests.Data.Core
target.Subscribe(x => result.Add(x));
}
[Fact]
public void RootGetter_Is_Reevaluated_On_Subscribe()
{
var data = "foo";
var target = new ExpressionObserver(() => data, new EmptyExpressionNode(), new Subject<Unit>(), null);
var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x));
Assert.Equal(new object[] { "foo" }, result);
sub.Dispose();
data = "bar";
target.Subscribe(x => result.Add(x));
Assert.Equal(new object[] { "foo", "bar" }, result);
}
public class MyViewModelBase { public object Name => "Name"; }
public class MyViewModel : MyViewModelBase { public new string Name => "NewName"; }

Loading…
Cancel
Save