/// <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);
        }