/// <summary>
        ///     Observes a property that implements INotifyPropertyChanged, and automatically calls a custom action on
        ///     property changed notifications. The given expression must be in this form: "() =&gt;
        ///     Prop.NestedProp.PropToObserve".
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="propertyExpression">
        ///     Expression representing property to be observed. Ex.: "() =&gt;
        ///     Prop.NestedProp.PropToObserve".
        /// </param>
        /// <param name="action">Action to be invoked when PropertyChanged event occours.</param>
        /// <param name="isAutoSubscribe">if set to <c>true</c> [is automatic subscribe].</param>
        /// <returns></returns>
        public static ParameterObserver2 <T> Observes <T>(
            Expression <Func <T> > propertyExpression,
            Action <T> action,
            bool isAutoSubscribe = true)
        {
            var observer = new ParameterObserver2 <T>(propertyExpression.Body, propertyExpression.Compile(), action);

            if (isAutoSubscribe)
            {
                observer.Subscribe();
            }

            return(observer);
        }
        /// <summary>
        ///     Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        ///     <see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise,
        ///     <see langword="false" />.
        /// </returns>
        public bool Equals(ParameterObserver2 <TValue> other)
        {
            if (other is null)
            {
                return(false);
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return(Equals(this.ExpressionString, other.ExpressionString) && Equals(this.Owner, other.Owner));
        }
        /// <summary>
        ///     Observes the specified owner.
        /// </summary>
        /// <typeparam name="TOwner">The type of the owner.</typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="owner">The owner.</param>
        /// <param name="propertyExpression">The property expression.</param>
        /// <param name="action">The action.</param>
        /// <param name="isAutoSubscribe">if set to <c>true</c> [is automatic subscribe].</param>
        /// <returns></returns>
        public static ParameterObserver2 <T> Observes <TOwner, T>(
            TOwner owner,
            Expression <Func <TOwner, T> > propertyExpression,
            Action <T> action,
            bool isAutoSubscribe = true)
        {
            ParameterObserver2 <T> observer = null;

            observer = new ParameterObserver2 <T>(
                owner,
                propertyExpression.Body,
                () => propertyExpression.Compile()((TOwner)observer.Owner),
                action);
            if (isAutoSubscribe)
            {
                observer.Subscribe();
            }

            return(observer);
        }