/// <summary>
        /// Converts target property's ErrorsChanged to an observable sequence.
        /// </summary>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        public static IObservable <TProperty> ObserveErrorInfo <TSubject, TProperty>(
            this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector)
            where TSubject : INotifyDataErrorInfo
        {
            string propertyName;
            var    accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out propertyName);

            var result = subject.ErrorsChangedAsObservable()
                         .Where(e => e.PropertyName == propertyName)
                         .Select(_ => ((Func <TSubject, TProperty>)accessor).Invoke(subject));

            return(result);
        }
        /// <summary>
        /// Converts NotificationObject's property changed to an observable sequence.
        /// </summary>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="isPushCurrentValueOnSubscribe">Push current value on first subscribe.</param>
        public static IObservable <TProperty> ObserveProperty <TSubject, TProperty>(
            this TSubject subject, Expression <Func <TSubject, TProperty> > propertySelector,
            bool isPushCurrentValueAtFirst = true)
            where TSubject : INotifyPropertyChanged
        {
            string propertyName;
            var    accessor = AccessorCache <TSubject> .LookupGet(propertySelector, out propertyName);

            var isFirst = true;

            var result = Observable.Defer(() =>
            {
                var flag = isFirst;
                isFirst  = false;

                var q = subject.PropertyChangedAsObservable()
                        .Where(e => e.PropertyName == propertyName)
                        .Select(_ => accessor.Invoke(subject));
                return((isPushCurrentValueAtFirst && flag) ? q.StartWith(accessor.Invoke(subject)) : q);
            });

            return(result);
        }