From 6bd5f85d4d924caccda85ce8b3d757d57b2d3f32 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 19 Oct 2015 11:05:44 +0200 Subject: [PATCH] Update Owner when AddOwnering properties. --- src/Perspex.Base/PerspexProperty.cs | 56 +++++++++++++++++-- src/Perspex.Base/PerspexProperty`1.cs | 28 ++++++++-- .../PerspexPropertyTests.cs | 18 ++++++ 3 files changed, 94 insertions(+), 8 deletions(-) diff --git a/src/Perspex.Base/PerspexProperty.cs b/src/Perspex.Base/PerspexProperty.cs index 62a3d5cfe2..2dd679ce8d 100644 --- a/src/Perspex.Base/PerspexProperty.cs +++ b/src/Perspex.Base/PerspexProperty.cs @@ -29,7 +29,12 @@ namespace Perspex private static int s_nextId = 1; /// - /// The default values for the property, by type. + /// The default value provided when the property was first registered. + /// + private readonly object _defaultValue; + + /// + /// The overridden default values for the property, by type. /// private readonly Dictionary _defaultValues = new Dictionary(); @@ -93,7 +98,7 @@ namespace Perspex Name = name; PropertyType = valueType; OwnerType = ownerType; - _defaultValues.Add(ownerType, defaultValue); + _defaultValue = defaultValue; Inherits = inherits; DefaultBindingMode = defaultBindingMode; IsAttached = isAttached; @@ -144,14 +149,57 @@ namespace Perspex /// Initializes a new instance of the class. /// /// The direct property to copy. + /// The new owner type. + protected PerspexProperty(PerspexProperty source, Type ownerType) + { + Contract.Requires(source != null); + Contract.Requires(ownerType != null); + + if (source.IsDirect) + { + throw new InvalidOperationException( + "This method cannot be called on direct PerspexProperties."); + } + + //Name = name; + //PropertyType = valueType; + //OwnerType = ownerType; + //_defaultValues.Add(ownerType, defaultValue); + //Inherits = inherits; + //DefaultBindingMode = defaultBindingMode; + //IsAttached = isAttached; + //Notifying = notifying; + //_id = s_nextId++; + + + Name = source.Name; + PropertyType = source.PropertyType; + OwnerType = ownerType; + _defaultValue = source._defaultValue; + _defaultValues = source._defaultValues; + Inherits = source.Inherits; + DefaultBindingMode = source.DefaultBindingMode; + IsAttached = false; + Notifying = Notifying; + _validation = source._validation; + _id = source._id; + } + + /// + /// Initializes a new instance of the class. + /// + /// The direct property to copy. + /// The new owner type. /// A new getter. /// A new setter. protected PerspexProperty( PerspexProperty source, + Type ownerType, Func getter, Action setter) { Contract.Requires(source != null); + Contract.Requires(ownerType != null); Contract.Requires(getter != null); if (!source.IsDirect) @@ -162,7 +210,7 @@ namespace Perspex Name = source.Name; PropertyType = source.PropertyType; - OwnerType = source.OwnerType; + OwnerType = ownerType; Getter = getter; Setter = setter; IsDirect = true; @@ -530,7 +578,7 @@ namespace Perspex type = type.GetTypeInfo().BaseType; } - return _defaultValues[OwnerType]; + return _defaultValue; } /// diff --git a/src/Perspex.Base/PerspexProperty`1.cs b/src/Perspex.Base/PerspexProperty`1.cs index 9a39b95c0c..6d97833f0a 100644 --- a/src/Perspex.Base/PerspexProperty`1.cs +++ b/src/Perspex.Base/PerspexProperty`1.cs @@ -66,17 +66,29 @@ namespace Perspex Setter = setter; } + /// + /// Initializes a new instance of the class. + /// + /// The property to copy. + /// The new owner type. + private PerspexProperty(PerspexProperty source, Type ownerType) + : base(source, ownerType) + { + } + /// /// Initializes a new instance of the class. /// /// The direct property to copy. + /// The new owner type. /// A new getter. /// A new setter. private PerspexProperty( PerspexProperty source, + Type ownerType, Func getter, Action setter) - : base(source, CastParamReturn(getter), CastParams(setter)) + : base(source, ownerType, CastParamReturn(getter), CastParams(setter)) { Getter = getter; Setter = setter; @@ -105,8 +117,9 @@ namespace Perspex "You must provide a new getter and setter when calling AddOwner on a direct PerspexProperty."); } - PerspexPropertyRegistry.Instance.Register(typeof(TOwner), this); - return this; + var result = new PerspexProperty(this, typeof(TOwner)); + PerspexPropertyRegistry.Instance.Register(typeof(TOwner), result); + return result; } /// @@ -119,8 +132,15 @@ namespace Perspex Action setter = null) where TOwner : PerspexObject { + if (!IsDirect) + { + throw new InvalidOperationException( + "This overload of AddOwner is for direct PerspexProperties."); + } + var result = new PerspexProperty( - this, + this, + typeof(TOwner), CastReturn(getter), CastParam1(setter)); diff --git a/tests/Perspex.Base.UnitTests/PerspexPropertyTests.cs b/tests/Perspex.Base.UnitTests/PerspexPropertyTests.cs index 6c90ac1039..c858152da5 100644 --- a/tests/Perspex.Base.UnitTests/PerspexPropertyTests.cs +++ b/tests/Perspex.Base.UnitTests/PerspexPropertyTests.cs @@ -161,6 +161,15 @@ namespace Perspex.Base.UnitTests Assert.True(p1 == p2); } + [Fact] + public void AddOwnered_Property_Should_Have_OwnerType_Set() + { + var p1 = new PerspexProperty("p1", typeof(Class1)); + var p2 = p1.AddOwner(); + + Assert.Equal(typeof(Class3), p2.OwnerType); + } + [Fact] public void AddOwnered_Direct_Property_Should_Equal_Original() { @@ -172,6 +181,15 @@ namespace Perspex.Base.UnitTests Assert.True(p1 == p2); } + [Fact] + public void AddOwnered_Direct_Property_Should_Have_OwnerType_Set() + { + var p1 = new PerspexProperty("d1", typeof(Class1), o => null, (o, v) => { }); + var p2 = p1.AddOwner(o => null, (o, v) => { }); + + Assert.Equal(typeof(Class3), p2.OwnerType); + } + [Fact] public void AddOwner_With_Getter_And_Setter_On_Standard_Property_Should_Throw() {