public static TViewModel TrackModel <TViewModel>(this IReactiveElement parentModel, IServiceProvider serviceProvider)
            where TViewModel : class, IReactiveElement
        {
            var model = parentModel.DeferDispose(serviceProvider.CreateInstance <TViewModel>());

            parentModel.TrackModel(model);

            return(model);
        }
        public static IDisposable Effect <T>(this IReactiveElement self, IObservable <T> stream, Action <T> reaction)
        {
            var context = SynchronizationContext.Current;

            if (context != null)
            {
                stream = stream.ObserveOn(context);
            }
            return(self.DeferDispose(stream.Subscribe(reaction)));
        }
        public static Property <T> Property <T>(
            this IReactiveElement self,
            T?initialValue,
            Func <T?, T?, T?>?coerceValue  = null,
            IEqualityComparer <T>?comparer = null)
        {
            if (self is null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            var property = self.DeferDispose(
                new Property <T>(initialValue, coerceValue, comparer));

            return(property);
        }
        public static Command Command(this IReactiveElement self)
        {
            if (self is null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            var command = self.DeferDispose(new Command());

            //// Logging
            //self.Effect(
            //    command,
            //    () => Console.WriteLine($"OnCommand: {self.GetType().Name}()"));

            return(command);
        }
        public static TReactive Reactive <TValue, TCommand, TError, TReactive>(
            this IReactiveElement self,
            Func <IObservable <LoadingResult <TValue, TError> >, TReactive> factory,
            TCommand?initialCommand,
            IObservable <TCommand?> reloadCommand,
            Func <TCommand?, IObservable <TValue> > loadProperty,
            Func <Exception, TError> onError)
            where TReactive : class, IUpdatableElement, IDisposable
        {
            var updates = CreateUpdates(initialCommand, reloadCommand, loadProperty, onError)
                          .Replay(1);

            self.DeferDispose(updates.Connect());

            return(self.Reactive(
                       factory,
                       LoadingResult.Create <TValue, TError>().StartLoading(),
                       updates));
        }
        public static TReactive CreateReactive <T, TReactive>(
            this IReactiveElement self,
            IObservable <T> valueStream,
            Func <IObservable <T>, TReactive> factory)
            where TReactive : class, IUpdatableElement, IDisposable
        {
            if (self is null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            if (valueStream is null)
            {
                throw new ArgumentNullException(nameof(valueStream));
            }

            var reactive = factory(valueStream);

            self.Effect(reactive.ValueChanged, self.StateChanged.Call);

            return(self.DeferDispose(reactive));
        }
 public static void DeferDispose(this IReactiveElement self, Action dispose) =>
 self.DeferDispose(new Disposable(dispose));