public void Should_Track_NonIntegerIndexer() { var data = new { Foo = new NonIntegerIndexer() }; data.Foo["foo"] = "bar"; data.Foo["baz"] = "qux"; var target = ExpressionObserverBuilder.Build(data, "Foo[foo]"); var result = new List <object>(); using (var sub = target.Subscribe(x => result.Add(x))) { data.Foo["foo"] = "bar2"; } // Forces WeakEvent compact Dispatcher.UIThread.RunJobs(); var expected = new[] { "bar", "bar2" }; Assert.Equal(expected, result); Assert.Equal(0, data.Foo.PropertyChangedSubscriptionCount); GC.KeepAlive(data); }
public void Should_Update_Value_After_Root_Changes_With_ComplexPath() { var root = new { DataContext = new { Foo = new { Value = "Foo" } } }; var subject = new Subject <object>(); var obs = ExpressionObserverBuilder.Build(subject, "DataContext.Foo.Value"); var values = new List <object>(); obs.Subscribe(v => values.Add(v)); subject.OnNext(root); subject.OnNext(null); subject.OnNext(root); Assert.Equal("Foo", values[0]); Assert.IsType <BindingNotification>(values[1]); var bn = values[1] as BindingNotification; Assert.Equal(AvaloniaProperty.UnsetValue, bn.Value); Assert.Equal(BindingErrorType.Error, bn.ErrorType); Assert.Equal(3, values.Count); Assert.Equal("Foo", values[2]); }
public void Should_Have_Null_ResultType_For_Broken_Chain() { var data = new { Foo = new { Bar = 1 } }; var target = ExpressionObserverBuilder.Build(data, "Foo.Bar.Baz"); Assert.Null(target.ResultType); GC.KeepAlive(data); }
private ExpressionObserver CreateSourceObserver( object source, string path, bool enableDataValidation) { Contract.Requires <ArgumentNullException>(source != null); return(ExpressionObserverBuilder.Build(source, path, enableDataValidation, typeResolver: TypeResolver)); }
public async Task Should_Get_UnsetValue_For_Object_Without_Indexer() { var data = new { Foo = 5 }; var target = ExpressionObserverBuilder.Build(data, "Foo[noindexer]"); var result = await target.Take(1); Assert.Equal(AvaloniaProperty.UnsetValue, result); GC.KeepAlive(data); }
public async Task Should_Negate_True_String() { var data = new { Foo = "True" }; var target = ExpressionObserverBuilder.Build(data, "!Foo"); var result = await target.Take(1); Assert.False((bool)result); GC.KeepAlive(data); }
public async Task Should_Get_UnsetValue_For_Invalid_Array_Index() { var data = new { Foo = new[] { "foo", "bar" } }; var target = ExpressionObserverBuilder.Build(data, "Foo[invalid]"); var result = await target.Take(1); Assert.Equal(AvaloniaProperty.UnsetValue, result); GC.KeepAlive(data); }
public async Task Should_Get_Attached_Property_Value() { var data = new Class1(); var target = ExpressionObserverBuilder.Build(data, "(Owner.Foo)", typeResolver: _typeResolver); var result = await target.Take(1); Assert.Equal("foo", result); Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers()); }
public InstancedBinding ItemsSelector(object item) { if (ItemsSource != null) { var obs = ExpressionObserverBuilder.Build(item, ItemsSource.Path); return(InstancedBinding.OneWay(obs, BindingPriority.Style)); } return(null); }
public async Task Should_Get_Array_Value() { var data = new { Foo = new[] { "foo", "bar" } }; var target = ExpressionObserverBuilder.Build(data, "Foo[1]"); var result = await target.Take(1); Assert.Equal("bar", result); GC.KeepAlive(data); }
public async Task Indexer_Only_Binding_Works() { var data = new[] { 1, 2, 3 }; var target = ExpressionObserverBuilder.Build(data, "[1]"); var value = await target.Take(1); Assert.Equal(data[1], value); }
public async Task Array_With_Wrong_Dimensions_Should_Return_UnsetValue() { var data = new { Foo = new[] { "foo", "bar" } }; var target = ExpressionObserverBuilder.Build(data, "Foo[1,2]"); var result = await target.Take(1); Assert.Equal(AvaloniaProperty.UnsetValue, result); GC.KeepAlive(data); }
public async Task Should_Get_AvaloniaProperty_By_Name() { var data = new Class1(); var target = ExpressionObserverBuilder.Build(data, "Foo"); var result = await target.Take(1); Assert.Equal("foo", result); Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers()); }
public async Task Should_Get_Method_WithCorrectDelegateType(string methodName, Type expectedType) { var data = new TestObject(); var observer = ExpressionObserverBuilder.Build(data, methodName); var result = await observer.Take(1); Assert.IsType(expectedType, result); GC.KeepAlive(data); }
public async Task Should_Get_Method() { var data = new TestObject(); var observer = ExpressionObserverBuilder.Build(data, nameof(TestObject.MethodWithoutReturn)); var result = await observer.Take(1); Assert.NotNull(result); GC.KeepAlive(data); }
public async Task Should_Negate_BindingNotification_Value() { var data = new { Foo = true }; var target = ExpressionObserverBuilder.Build(data, "!Foo", enableDataValidation: true); var result = await target.Take(1); Assert.Equal(new BindingNotification(false), result); GC.KeepAlive(data); }
public void SetValue_Should_Return_False_For_Invalid_Value() { var data = new { Foo = "foo" }; var target = ExpressionObserverBuilder.Build(data, "!Foo"); target.Subscribe(_ => { }); Assert.False(target.SetValue("bar")); GC.KeepAlive(data); }
public async Task Should_Get_Value_For_Non_String_Indexer() { var data = new { Foo = new Dictionary <double, string> { { 1.0, "bar" }, { 2.0, "qux" } } }; var target = ExpressionObserverBuilder.Build(data, "Foo[1.0]"); var result = await target.Take(1); Assert.Equal("bar", result); GC.KeepAlive(data); }
public async Task Can_Call_Method_Returned_From_Observer() { var data = new TestObject(); var observer = ExpressionObserverBuilder.Build(data, nameof(TestObject.MethodWithReturnAndParameters)); var result = await observer.Take(1); var callback = (Func <int, int>)result; Assert.Equal(1, callback(1)); GC.KeepAlive(data); }
public async Task List_Out_Of_Bounds_Should_Return_UnsetValue() { var data = new { Foo = new List <string> { "foo", "bar" } }; var target = ExpressionObserverBuilder.Build(data, "Foo[2]"); var result = await target.Take(1); Assert.Equal(AvaloniaProperty.UnsetValue, result); GC.KeepAlive(data); }
public async Task Should_Get_Attached_Property_Value_With_Namespace() { var data = new Class1(); var target = ExpressionObserverBuilder.Build( data, "(NS:Owner.Foo)", typeResolver: (ns, name) => ns == "NS" && name == "Owner" ? typeof(Owner) : null); var result = await target.Take(1); Assert.Equal("foo", result); Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers()); }
public async Task Should_Get_MultiDimensional_Array_Value() { var data = new { Foo = new[, ] { { "foo", "bar" }, { "baz", "qux" } } }; var target = ExpressionObserverBuilder.Build(data, "Foo[1, 1]"); var result = await target.Take(1); Assert.Equal("qux", result); GC.KeepAlive(data); }
public async Task Should_Return_Error_Notification_If_Too_Many_Parameters(string methodName) { var data = new TestObject(); var observer = ExpressionObserverBuilder.Build(data, methodName); var result = await observer.Take(1); Assert.IsType <BindingNotification>(result); Assert.Equal(BindingErrorType.Error, ((BindingNotification)result).ErrorType); GC.KeepAlive(data); }
public object Select(object o) { if (string.IsNullOrEmpty(MemberName)) { return(o); } var expression = ExpressionObserverBuilder.Build(o, MemberName); object result = AvaloniaProperty.UnsetValue; expression.Subscribe(x => result = x); return((result == AvaloniaProperty.UnsetValue || result is BindingNotification) ? null : result); }
public async Task Should_Pass_Through_BindingNotification_Error() { var data = new { }; var target = ExpressionObserverBuilder.Build(data, "!Foo", enableDataValidation: true); var result = await target.Take(1); Assert.Equal( new BindingNotification( new MissingMemberException("Could not find a matching property accessor for 'Foo' on '{ }'"), BindingErrorType.Error), result); GC.KeepAlive(data); }
public void Should_SetArrayIndex() { var data = new { Foo = new[] { "foo", "bar" } }; var target = ExpressionObserverBuilder.Build(data, "Foo[1]"); using (target.Subscribe(_ => { })) { Assert.True(target.SetValue("baz")); } Assert.Equal("baz", data.Foo[1]); GC.KeepAlive(data); }
public async Task Should_Return_BindingNotification_For_Value_Not_Convertible_To_Boolean() { var data = new { Foo = new object() }; var target = ExpressionObserverBuilder.Build(data, "!Foo"); var result = await target.Take(1); Assert.Equal( new BindingNotification( new InvalidCastException($"Unable to convert 'System.Object' to bool."), BindingErrorType.Error), result); GC.KeepAlive(data); }
public async Task Should_Return_BindingNotification_Error_For_Broken_Chain() { var data = new { Foo = new { Bar = 1 } }; var target = ExpressionObserverBuilder.Build(data, "Foo.Bar.Baz"); var result = await target.Take(1); Assert.IsType <BindingNotification>(result); Assert.Equal( new BindingNotification( new MissingMemberException("Could not find a matching property accessor for 'Baz' on '1'"), BindingErrorType.Error), result); GC.KeepAlive(data); }
public InstancedBinding ItemsSelector(object item) { if (ItemsSource != null) { var obs = ItemsSource switch { Binding reflection => ExpressionObserverBuilder.Build(item, reflection.Path), CompiledBindingExtension compiled => new ExpressionObserver(item, compiled.Path.BuildExpression(false)), _ => throw new InvalidOperationException("TreeDataTemplate currently only supports Binding and CompiledBindingExtension!") }; return(InstancedBinding.OneWay(obs, BindingPriority.Style)); } return(null); }
public void Should_Track_Simple_Attached_Value() { var data = new Class1(); var target = ExpressionObserverBuilder.Build(data, "(Owner.Foo)", typeResolver: _typeResolver); var result = new List <object>(); var sub = target.Subscribe(x => result.Add(x)); data.SetValue(Owner.FooProperty, "bar"); Assert.Equal(new[] { "foo", "bar" }, result); sub.Dispose(); Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers()); }