From 962c1ea01b35fb9c100a897d055a5e0a7fa1d44c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 30 Sep 2015 20:48:53 +0200 Subject: [PATCH] Pass SetValue through expression chain. --- .../Perspex.Markup/Binding/ExpressionNode.cs | 8 +++-- .../Binding/ExpressionNodeBuilder.cs | 12 ++++--- .../Binding/ExpressionObserver.cs | 34 +++++++------------ .../Binding/PropertyAccessorNode.cs | 23 ++++++++----- .../Perspex.Markup/Properties/AssemblyInfo.cs | 2 ++ .../Binding/ExpressionNodeBuilderTests.cs | 18 ++++++++-- 6 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/Markup/Perspex.Markup/Binding/ExpressionNode.cs b/src/Markup/Perspex.Markup/Binding/ExpressionNode.cs index aec90ee070..114cd43b80 100644 --- a/src/Markup/Perspex.Markup/Binding/ExpressionNode.cs +++ b/src/Markup/Perspex.Markup/Binding/ExpressionNode.cs @@ -2,12 +2,11 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Reactive; using System.Reactive.Subjects; namespace Perspex.Markup.Binding { - public abstract class ExpressionNode : IObservable + internal abstract class ExpressionNode : IObservable { private object _target; @@ -72,6 +71,11 @@ namespace Perspex.Markup.Binding } } + public virtual bool SetValue(object value) + { + return Next?.SetValue(value) ?? false; + } + public IDisposable Subscribe(IObserver observer) { if (Next != null) diff --git a/src/Markup/Perspex.Markup/Binding/ExpressionNodeBuilder.cs b/src/Markup/Perspex.Markup/Binding/ExpressionNodeBuilder.cs index ebd4b85baf..7d493066c7 100644 --- a/src/Markup/Perspex.Markup/Binding/ExpressionNodeBuilder.cs +++ b/src/Markup/Perspex.Markup/Binding/ExpressionNodeBuilder.cs @@ -1,16 +1,18 @@ -using System; +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Perspex.Markup.Binding { - public class ExpressionNodeBuilder + internal class ExpressionNodeBuilder { - public static IList Build(string expression) + public static ExpressionNode Build(string expression) { if (string.IsNullOrWhiteSpace(expression)) { @@ -45,7 +47,7 @@ namespace Perspex.Markup.Binding result[i].Next = result[i + 1]; } - return result; + return result[0]; } else { diff --git a/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs b/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs index cdbeddda0c..bd0b08b7c3 100644 --- a/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs +++ b/src/Markup/Perspex.Markup/Binding/ExpressionObserver.cs @@ -15,6 +15,7 @@ namespace Perspex.Markup.Binding public class ExpressionObserver : ObservableBase { private int _count; + private ExpressionNode _node; /// /// Initializes a new instance of the class. @@ -24,7 +25,7 @@ namespace Perspex.Markup.Binding public ExpressionObserver(object root, string expression) { Root = root; - Nodes = ExpressionNodeBuilder.Build(expression); + _node = ExpressionNodeBuilder.Build(expression); } /// @@ -37,22 +38,16 @@ namespace Perspex.Markup.Binding /// public bool SetValue(object value) { - var last = Nodes.Last() as PropertyAccessorNode; + IncrementCount(); - if (last != null) + try { - try - { - IncrementCount(); - return last.SetValue(value); - } - finally - { - DecrementCount(); - } + return _node.SetValue(value); + } + finally + { + DecrementCount(); } - - return false; } /// @@ -60,17 +55,12 @@ namespace Perspex.Markup.Binding /// public object Root { get; } - /// - /// Gets a list of nodes representing the parts of the expression. - /// - public IList Nodes { get; } - /// protected override IDisposable SubscribeCore(IObserver observer) { IncrementCount(); - var subscription = Nodes[0].Subscribe(observer); + var subscription = _node.Subscribe(observer); return Disposable.Create(() => { @@ -83,7 +73,7 @@ namespace Perspex.Markup.Binding { if (_count++ == 0) { - Nodes[0].Target = Root; + _node.Target = Root; } } @@ -91,7 +81,7 @@ namespace Perspex.Markup.Binding { if (--_count == 0) { - Nodes[0].Target = null; + _node.Target = null; } } } diff --git a/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs b/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs index 351879d1b4..27e931a089 100644 --- a/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs +++ b/src/Markup/Perspex.Markup/Binding/PropertyAccessorNode.cs @@ -7,7 +7,7 @@ using System.Reflection; namespace Perspex.Markup.Binding { - public class PropertyAccessorNode : ExpressionNode + internal class PropertyAccessorNode : ExpressionNode { private PropertyInfo _propertyInfo; @@ -16,19 +16,26 @@ namespace Perspex.Markup.Binding PropertyName = propertyName; } - public bool SetValue(object value) + public string PropertyName { get; } + + public override bool SetValue(object value) { - if (_propertyInfo != null) + if (Next != null) { - _propertyInfo.SetValue(Target, value); - return true; + return Next.SetValue(value); } + else + { + if (_propertyInfo != null) + { + _propertyInfo.SetValue(Target, value); + return true; + } - return false; + return false; + } } - public string PropertyName { get; } - protected override void SubscribeAndUpdate(object target) { var result = ExpressionValue.None; diff --git a/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs b/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs index c3a8edb54e..9076f81754 100644 --- a/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs +++ b/src/Markup/Perspex.Markup/Properties/AssemblyInfo.cs @@ -28,3 +28,5 @@ using System.Runtime.InteropServices; // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: InternalsVisibleTo("Perspex.Markup.UnitTests")] \ No newline at end of file diff --git a/tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests.cs b/tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests.cs index cdbbc1d1d3..443d18cdef 100644 --- a/tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests.cs +++ b/tests/Perspex.Markup.UnitTests/Binding/ExpressionNodeBuilderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System.Collections.Generic; using Perspex.Markup.Binding; using Xunit; @@ -11,7 +12,7 @@ namespace Perspex.Markup.UnitTests.Binding [Fact] public void Should_Build_Single_Property() { - var result = ExpressionNodeBuilder.Build("Foo"); + var result = ToList(ExpressionNodeBuilder.Build("Foo")); Assert.Equal(1, result.Count); Assert.IsType(result[0]); @@ -20,10 +21,23 @@ namespace Perspex.Markup.UnitTests.Binding [Fact] public void Should_Build_Property_Chain() { - var result = ExpressionNodeBuilder.Build("Foo.Bar.Baz"); + var result = ToList(ExpressionNodeBuilder.Build("Foo.Bar.Baz")); Assert.Equal(3, result.Count); Assert.IsType(result[0]); } + + private List ToList(ExpressionNode node) + { + var result = new List(); + + while (node != null) + { + result.Add(node); + node = node.Next; + } + + return result; + } } }