using System; using System.Collections.Generic; using Avalonia.Collections; using Avalonia.Data.Core; using Avalonia.UnitTests; using Xunit; namespace Avalonia.LeakTests { public class BindingExpressionTests : ScopedTestBase { [Fact] public void Should_Not_Keep_Source_Alive_ObservableCollection() { static WeakReference CreateExpression() { var list = new AvaloniaList { "foo", "bar" }; var source = new { Foo = list }; var target = BindingExpression.Create(source, o => o.Foo); target.ToObservable().Subscribe(_ => { }); return new WeakReference(list); } var weakSource = CreateExpression(); Assert.True(weakSource.IsAlive); GC.Collect(); Assert.False(weakSource.IsAlive); } [Fact] public void Should_Not_Keep_Source_Alive_ObservableCollection_With_DataValidation() { static WeakReference CreateExpression() { var list = new AvaloniaList { "foo", "bar" }; var source = new { Foo = list }; var target = BindingExpression.Create(source, o => o.Foo, enableDataValidation: true); target.ToObservable().Subscribe(_ => { }); return new WeakReference(list); } var weakSource = CreateExpression(); Assert.True(weakSource.IsAlive); GC.Collect(); Assert.False(weakSource.IsAlive); } [Fact] public void Should_Not_Keep_Source_Alive_NonIntegerIndexer() { static WeakReference CreateExpression() { var indexer = new NonIntegerIndexer(); var source = new { Foo = indexer }; var target = BindingExpression.Create(source, o => o.Foo); target.ToObservable().Subscribe(_ => { }); return new WeakReference(indexer); } var weakSource = CreateExpression(); Assert.True(weakSource.IsAlive); GC.Collect(); Assert.False(weakSource.IsAlive); } [Fact] public void Should_Not_Keep_Source_Alive_MethodBinding() { static WeakReference CreateExpression() { var methodBound = new MethodBound(); var source = new { Foo = methodBound }; var target = BindingExpression.Create(source, o => (Action)o.Foo.A); target.ToObservable().Subscribe(_ => { }); return new WeakReference(methodBound); } var weakSource = CreateExpression(); Assert.True(weakSource.IsAlive); GC.Collect(); Assert.False(weakSource.IsAlive); } private class MethodBound { public void A() { } } private class NonIntegerIndexer : NotifyingBase { private readonly Dictionary _storage = new Dictionary(); public string this[string key] { get { return _storage[key]; } set { _storage[key] = value; RaisePropertyChanged(CommonPropertyNames.IndexerName); } } } } }