/// <summary> /// Creates the graph. /// </summary> /// <returns></returns> /// <exception cref="NotSupportedException"> /// Operation not supported for the given expression type {expression.Type}. " /// + "Only MemberExpression and ConstantExpression are currently supported. /// </exception> /// <exception cref="InvalidOperationException"> /// Trying to subscribe PropertyChanged listener in object that " /// + $"owns '{rootPropertyInfo.Name}' property, but the object does not implements INotifyPropertyChanged. /// </exception> /// <exception cref="System.NotSupportedException"> /// Operation not supported for the given expression type. " /// + "Only MemberExpression and ConstantExpression are currently supported. /// </exception> /// <exception cref="System.InvalidOperationException"> /// Trying to subscribe PropertyChanged listener in object that " /// + $"owns '{parameterObserverRootNode.PropertyInfo.Name}' property, but the object does not implements /// INotifyPropertyChanged. /// </exception> private (ParameterObserverRootNode <TOwner>, string) CreateChain() { var expression = this.propertyExpression; var expressionString = ""; var propertyInfos = new Stack <PropertyInfo>(); while (expression is MemberExpression memberExpression) { if (!(memberExpression.Member is PropertyInfo propertyInfo)) { continue; } expression = memberExpression.Expression; propertyInfos.Push(propertyInfo); } if (!(expression is ConstantExpression constantExpression)) { throw new NotSupportedException( $"Operation not supported for the given expression type {expression.Type}. " + "Only MemberExpression and ConstantExpression are currently supported."); } var rootPropertyInfo = propertyInfos.Pop(); expressionString = OwnerString + this.propertyExpression.ToString() .Remove(0, constantExpression.ToString().Length); if (!(constantExpression.Value is IReadOnlyParameter parameter)) { throw new InvalidOperationException( "Trying to subscribe PropertyChanged listener in object that " + $"owns '{rootPropertyInfo.Name}' property, but the object does not implements IReadOnlyParameter."); } if (!(constantExpression.Value is TOwner owner)) { throw new InvalidOperationException( "Trying to subscribe PropertyChanged listener in object that " + $"owns '{rootPropertyInfo.Name}' property, but the object does not of type '{typeof(TOwner).Name}'."); } var root = new ParameterObserverRootNode <TOwner>(rootPropertyInfo, this.CallAction, owner, parameter); ParameterObserverNode previousNode = root; foreach (var currentNode in propertyInfos.Select(name => new ParameterObserverNode(name, this.CallAction))) { previousNode.Next = currentNode; previousNode = currentNode; } return(root, expressionString); }
/// <summary> /// Creates the chain. /// </summary> /// <param name="owner">The owner.</param> /// <returns></returns> /// <exception cref="NotSupportedException"> /// Operation not supported for the given expression type {expression.Type}. " /// + "Only MemberExpression and ConstantExpression are currently supported. /// </exception> private (IParameterObserverRootNode <TOwner>, string) CreateChain(TOwner owner) { var expression = this.propertyExpression; var expressionString = ""; var propertyInfos = new Stack <PropertyInfo>(); while (expression is MemberExpression memberExpression) { if (!(memberExpression.Member is PropertyInfo info)) { continue; } expression = memberExpression.Expression; propertyInfos.Push(info); } if (!(expression is ParameterExpression parameterExpression)) { throw new NotSupportedException( $"Operation not supported for the given expression type {expression.Type}. " + "Only MemberExpression and ConstantExpression are currently supported."); } var rootPropertyInfo = propertyInfos.Pop(); expressionString = OwnerString + this.propertyExpression.ToString() .Remove(0, parameterExpression.ToString().Length); ParameterObserverRootNode <TOwner> parameterObserverRoot; if (owner is IReadOnlyParameter p) { if (!propertyInfos.Any()) { return(new ParameterObserverSingleNode <TOwner>(this.CallAction, owner, p), expressionString); } parameterObserverRoot = new ParameterObserverRootNode <TOwner>( rootPropertyInfo, this.CallAction, owner, p); } else { if (!(rootPropertyInfo.GetValue(owner) is IReadOnlyParameter v)) { throw new Exception("No Parameter."); } if (!propertyInfos.Any()) { return(new ParameterObserverSingleNode <TOwner>(this.CallAction, owner, v), expressionString); } var propertyInfo = propertyInfos.Pop(); if (typeof(IReadOnlyParameter).IsAssignableFrom(propertyInfo.PropertyType)) { parameterObserverRoot = new ParameterObserverRootNode <TOwner>( propertyInfo, this.CallAction, owner, v); } else { propertyInfo = propertyInfos.Pop(); if (typeof(IReadOnlyParameter).IsAssignableFrom(propertyInfo.PropertyType)) { parameterObserverRoot = new ParameterObserverRootNode <TOwner>( propertyInfo, this.CallAction, owner, v); } else { throw new Exception("No Parameter 3."); } } } ParameterObserverNode previousNode = parameterObserverRoot; foreach (var node in propertyInfos .Where(currentNode => typeof(IReadOnlyParameter).IsAssignableFrom(currentNode.PropertyType)) .Select(currentNode => new ParameterObserverNode(currentNode, this.CallAction))) { previousNode.Next = node; previousNode = node; } var endNode = new ParameterObserverEndNode(this.CallAction); previousNode.Next = endNode; return(parameterObserverRoot, expressionString); }