Browse Source

Ensure active direct bindings don't get collected.

pull/484/head
Steven Kirk 10 years ago
parent
commit
bc7c0ece15
  1. 24
      src/Perspex.Base/PerspexObject.cs
  2. 44
      tests/Perspex.Base.UnitTests/PerspexObjectTests_Direct.cs

24
src/Perspex.Base/PerspexObject.cs

@ -25,6 +25,17 @@ namespace Perspex
/// </remarks>
public class PerspexObject : IPerspexObject, IPerspexObjectDebug, INotifyPropertyChanged
{
/// <summary>
/// Maintains a list of direct property binding subscriptions so that the binding source
/// doesn't get collected.
/// </summary>
/// <remarks>
/// If/when we provide a ClearBindings() method, then this collection will be need to be
/// moved to an instance field and indexed by property, but until that point a static
/// collection will suffice.
/// </remarks>
private static List<IDisposable> s_directBindings = new List<IDisposable>();
/// <summary>
/// The parent object that inherited values are inherited from.
/// </summary>
@ -401,9 +412,20 @@ namespace Perspex
property,
GetDescription(source));
return source
IDisposable subscription = null;
subscription = source
.Select(x => TypeUtilities.CastOrDefault(x, property.PropertyType))
.Do(_ => { }, () => s_directBindings.Remove(subscription))
.Subscribe(x => SetValue(property, x));
s_directBindings.Add(subscription);
return Disposable.Create(() =>
{
subscription.Dispose();
s_directBindings.Remove(subscription);
});
}
else
{

44
tests/Perspex.Base.UnitTests/PerspexObjectTests_Direct.cs

@ -333,6 +333,50 @@ namespace Perspex.Base.UnitTests
Assert.Equal("second", target.Foo);
}
[Fact]
public void Binding_To_Direct_Property_Does_Not_Get_Collected()
{
var target = new Class2();
Func<WeakReference> setupBinding = () =>
{
var source = new Subject<string>();
var sub = target.Bind((PerspexProperty)Class1.FooProperty, source);
return new WeakReference(source);
};
var weakSource = setupBinding();
GC.Collect();
Assert.True(weakSource.IsAlive);
}
[Fact]
public void Binding_To_Direct_Property_Gets_Collected_When_Completed()
{
var target = new Class2();
Func<WeakReference> setupBinding = () =>
{
var source = new Subject<string>();
var sub = target.Bind((PerspexProperty)Class1.FooProperty, source);
return new WeakReference(source);
};
var weakSource = setupBinding();
Action completeSource = () =>
{
((ISubject<string>)weakSource.Target).OnCompleted();
};
completeSource();
GC.Collect();
Assert.False(weakSource.IsAlive);
}
[Fact]
public void Property_Notifies_Initialized()
{

Loading…
Cancel
Save