public ExpressionNode BuildExpression(bool enableValidation) { ExpressionNode pathRoot = null; ExpressionNode path = null; foreach (var element in _elements) { ExpressionNode node = null; switch (element) { case NotExpressionPathElement _: node = new LogicalNotNode(); break; case PropertyElement prop: node = new PropertyAccessorNode(prop.Property.Name, enableValidation, new PropertyInfoAccessorPlugin(prop.Property, prop.AccessorFactory)); break; case ArrayElementPathElement arr: node = new PropertyAccessorNode(CommonPropertyNames.IndexerName, enableValidation, new ArrayElementPlugin(arr.Indices, arr.ElementType)); break; case VisualAncestorPathElement visualAncestor: node = new FindVisualAncestorNode(visualAncestor.AncestorType, visualAncestor.Level); break; case AncestorPathElement ancestor: node = new FindAncestorNode(ancestor.AncestorType, ancestor.Level); break; case SelfPathElement _: node = new SelfNode(); break; case ElementNameElement name: node = new ElementNameNode(name.NameScope, name.Name); break; case IStronglyTypedStreamElement stream: node = new StreamNode(stream.CreatePlugin()); break; case ITypeCastElement typeCast: node = new StrongTypeCastNode(typeCast.Type, typeCast.Cast); break; default: throw new InvalidOperationException($"Unknown binding path element type {element.GetType().FullName}"); } path = pathRoot is null ? (pathRoot = node) : path.Next = node; } return(pathRoot ?? new EmptyExpressionNode()); }
public void Should_Not_Throw_Exception_On_Duplicate_Properties() { // Repro of https://github.com/AvaloniaUI/Avalonia/issues/4733. var source = new MyViewModel(); var target = new PropertyAccessorNode("Name", false); target.Target = new WeakReference <object>(source); var result = new List <object>(); target.Subscribe(x => result.Add(x)); }
public void Should_Not_Throw_Exception_On_Unsubscribe_When_Already_Unsubscribed() { var source = new Class1 { Foo = "foo" }; var target = new PropertyAccessorNode("Foo", false); Assert.NotNull(target); target.Target = new WeakReference <object>(source); target.Subscribe(_ => { }); target.Unsubscribe(); target.Unsubscribe(); Assert.True(true); }
public void Should_Not_Throw_Exception_When_Enabling_Data_Validation_On_Missing_Member() { var source = new Class1(); var target = new PropertyAccessorNode("NotFound", true); target.Target = new WeakReference <object>(source); var result = new List <object>(); target.Subscribe(x => result.Add(x)); Assert.Equal( new object[] { new BindingNotification( new MissingMemberException("Could not find a matching property accessor for 'NotFound' on 'Avalonia.Base.UnitTests.Data.Core.ExpressionObserverTests_Property+Class1'"), BindingErrorType.Error), }, result); }
public (ExpressionNode?Node, SourceMode Mode) Parse(ref CharacterReader r) { ExpressionNode?rootNode = null; ExpressionNode?node = null; var(astNodes, mode) = BindingExpressionGrammar.Parse(ref r); foreach (var astNode in astNodes) { ExpressionNode?nextNode = null; switch (astNode) { case BindingExpressionGrammar.EmptyExpressionNode _: nextNode = new EmptyExpressionNode(); break; case BindingExpressionGrammar.NotNode _: nextNode = new LogicalNotNode(); break; case BindingExpressionGrammar.StreamNode _: nextNode = new StreamNode(); break; case BindingExpressionGrammar.PropertyNameNode propName: nextNode = new PropertyAccessorNode(propName.PropertyName, _enableValidation); break; case BindingExpressionGrammar.IndexerNode indexer: nextNode = new StringIndexerNode(indexer.Arguments); break; case BindingExpressionGrammar.AttachedPropertyNameNode attachedProp: nextNode = ParseAttachedProperty(attachedProp); break; case BindingExpressionGrammar.SelfNode _: nextNode = new SelfNode(); break; case BindingExpressionGrammar.AncestorNode ancestor: nextNode = ParseFindAncestor(ancestor); break; case BindingExpressionGrammar.NameNode elementName: nextNode = new ElementNameNode(_nameScope ?? throw new NotSupportedException("Invalid element name binding with null name scope!"), elementName.Name); break; case BindingExpressionGrammar.TypeCastNode typeCast: nextNode = ParseTypeCastNode(typeCast); break; } if (node is null) { rootNode = node = nextNode; } else { node.Next = nextNode; node = nextNode; } } return(rootNode, mode); }