Пример #1
0
        /// <summary>
        /// <para>Converts NotificationObject's property to ReactiveProperty. Value is two-way synchronized.</para>
        /// <para>PropertyChanged raise on selected scheduler.</para>
        /// </summary>
        /// <typeparam name="TSubject">The type of the subject.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="subject">The subject.</param>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="convert">Convert selector to ReactiveProperty.</param>
        /// <param name="convertBack">Convert selector to source.</param>
        /// <param name="mode">ReactiveProperty mode.</param>
        /// <returns></returns>
        public static ReactivePropertySlim <TResult> ToReactivePropertySlimAsSynchronized <TSubject, TProperty, TResult>(
            this TSubject subject,
            Expression <Func <TSubject, TProperty> > propertySelector,
            Func <IObservable <TProperty>, IObservable <TResult> > convert,
            Func <IObservable <TResult>, IObservable <TProperty> > convertBack,
            ReactivePropertyMode mode = ReactivePropertyMode.DistinctUntilChanged | ReactivePropertyMode.RaiseLatestValueOnSubscribe)
            where TSubject : INotifyPropertyChanged
        {
            if (ExpressionTreeUtils.IsNestedPropertyPath(propertySelector))
            {
                var         result     = new ReactivePropertySlim <TResult>(mode: mode);
                var         observer   = PropertyObservable.CreateFromPropertySelector(subject, propertySelector);
                IDisposable disposable = null;
                disposable = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .Subscribe(x => result.Value = x);
                convertBack(result)
                .Subscribe(x => observer.SetPropertyPathValue(x), _ => disposable.Dispose(), () => disposable.Dispose());
                return(result);
            }
            else
            {
                var setter = AccessorCache <TSubject> .LookupSet(propertySelector, out _);

                var         result     = new ReactivePropertySlim <TResult>(mode: mode);
                IDisposable disposable = null;
                disposable = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .Subscribe(x => result.Value = x);
                convertBack(result)
                .Subscribe(x => setter(subject, x), _ => disposable.Dispose(), () => disposable.Dispose());
                return(result);
            }
        }
Пример #2
0
        /// <summary>
        /// <para>Converts NotificationObject's property to ReactiveProperty. Value is two-way synchronized.</para>
        /// <para>PropertyChanged raise on selected scheduler.</para>
        /// </summary>
        /// <typeparam name="TSubject">The type of the subject.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="subject">The subject.</param>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="convert">Convert selector to ReactiveProperty.</param>
        /// <param name="convertBack">Convert selector to source.</param>
        /// <param name="raiseEventScheduler">The raise event scheduler.</param>
        /// <param name="mode">ReactiveProperty mode.</param>
        /// <param name="ignoreValidationErrorValue">Ignore validation error value.</param>
        /// <returns></returns>
        public static ReactiveProperty <TResult> ToReactivePropertyAsSynchronized <TSubject, TProperty, TResult>(
            this TSubject subject,
            Expression <Func <TSubject, TProperty> > propertySelector,
            Func <IObservable <TProperty>, IObservable <TResult> > convert,
            Func <IObservable <TResult>, IObservable <TProperty> > convertBack,
            IScheduler raiseEventScheduler,
            ReactivePropertyMode mode       = ReactivePropertyMode.DistinctUntilChanged | ReactivePropertyMode.RaiseLatestValueOnSubscribe,
            bool ignoreValidationErrorValue = false)
            where TSubject : INotifyPropertyChanged
        {
            if (ExpressionTreeUtils.IsNestedPropertyPath(propertySelector))
            {
                var observer = PropertyObservable.CreateFromPropertySelector(subject, propertySelector);
                var result   = convert(Observable.Using(() => observer, x => x)
                                       .StartWith(observer.GetPropertyPathValue()))
                               .ToReactiveProperty(raiseEventScheduler, mode: mode);
                convertBack(result.Where(_ => !ignoreValidationErrorValue || !result.HasErrors))
                .Subscribe(x => observer.SetPropertyPathValue(x));
                return(result);
            }
            else
            {
                var setter = AccessorCache <TSubject> .LookupSet(propertySelector, out _);

                var result = convert(subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true))
                             .ToReactiveProperty(raiseEventScheduler, mode: mode);
                convertBack(result.Where(_ => !ignoreValidationErrorValue || !result.HasErrors))
                .Subscribe(x => setter(subject, x));
                return(result);
            }
        }
        /// <summary>
        /// <para>Converts NotificationObject's property to ReactiveProperty. Value is two-way synchronized.</para>
        /// <para>PropertyChanged raise on selected scheduler.</para>
        /// </summary>
        /// <typeparam name="TSubject">The type of the subject.</typeparam>
        /// <typeparam name="TProperty">The type of the property.</typeparam>
        /// <param name="subject">The subject.</param>
        /// <param name="propertySelector">Argument is self, Return is target property.</param>
        /// <param name="raiseEventScheduler">The raise event scheduler.</param>
        /// <param name="mode">ReactiveProperty mode.</param>
        /// <param name="ignoreValidationErrorValue">Ignore validation error value.</param>
        /// <returns></returns>
        public static ReactiveProperty <TProperty> ToReactivePropertyAsSynchronized <TSubject, TProperty>(
            this TSubject subject,
            Expression <Func <TSubject, TProperty> > propertySelector,
            IScheduler raiseEventScheduler,
            ReactivePropertyMode mode       = ReactivePropertyMode.DistinctUntilChanged | ReactivePropertyMode.RaiseLatestValueOnSubscribe,
            bool ignoreValidationErrorValue = false)
            where TSubject : INotifyPropertyChanged
        {
            var setter = AccessorCache <TSubject> .LookupSet(propertySelector, out _);

            var result = subject.ObserveProperty(propertySelector, isPushCurrentValueAtFirst: true)
                         .ToReactiveProperty(raiseEventScheduler, mode: mode);

            result
            .Where(_ => !ignoreValidationErrorValue || !result.HasErrors)
            .Subscribe(x => setter(subject, x));

            return(result);
        }