public AppUIStore(AppDispatcher dispatcher, IReadAndWriteMessages messageApi)
        {
            if (dispatcher == null)
            {
                throw new ArgumentNullException("dispatcher");
            }
            if (messageApi == null)
            {
                throw new ArgumentNullException("messageApi");
            }

            NewMessage     = GetEmptyNewMessage();
            MessageHistory = NonNullList <SavedMessageDetails> .Empty;

            _saveActionRequestId = null;

            dispatcher.Receive(a => a
                               .If <StoreInitialised>(
                                   condition: action => action.Store == this,
                                   work: action =>
            {
                // When it's time for a Store to be initialised (to set its initial state and call OnChange to let any interested Components know
                // that it's ready), a StoreInitialised action will be dispatched that references the Store. In a more complicated app, a router
                // might choose an initial Store based upon the current URL. (We don't need to do anything within this callback, we just need to
                // match the StoreInitialised so that IfAnyMatched will fire and call OnChange).
            }
                                   )
                               .Else <MessageEditStateChanged>(action => NewMessage = UpdateValidationFor(action.NewState))
                               .Else <MessageSaveRequested>(action =>
            {
                NewMessage           = NewMessage.With(_ => _.IsSaveInProgress, true);
                _saveActionRequestId = messageApi.SaveMessage(action.Message);
            })
                               .Else <MessageSaveSucceeded>(
                                   condition: action => action.RequestId == _saveActionRequestId,
                                   work: action =>
            {
                // The API's SaveMessage function will fire a MessageSaveSucceeded action when (if) the save is successful and then a subsequent
                // MessageHistoryUpdated action after it's automatically retrieved fresh data, including the newly-saved item (so we need only
                // reset the form here, a MessageHistoryUpdated should be along shortly containig the new item..)
                _saveActionRequestId = null;
                NewMessage           = GetEmptyNewMessage();
            }
                                   )
                               .Else <MessageHistoryUpdated>(action => MessageHistory = action.Messages)
                               .IfAnyMatched(OnChange)
                               );
        }
示例#2
0
        public static void RunTests()
        {
            Module("AppDispatcher");

            Test("Broadcast action to single receiver", assert =>
            {
                var dispatcher = new AppDispatcher();
                dispatcher.Receive(action =>
                {
                    assert.Equal(action.GetType(), typeof(SomethingHappened));
                });
                dispatcher.Dispatch(new SomethingHappened());
            });

            Test("Broadcast action to two receivers, where the second to subscribe waits for the first to complete", assert =>
            {
                var dispatcher             = new AppDispatcher();
                var firstReceiverProcessed = false;
                var token = dispatcher.Receive(action =>
                {
                    firstReceiverProcessed = true;
                });
                dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token);
                    assert.Equal(firstReceiverProcessed, true);
                });
                dispatcher.Dispatch(new SomethingHappened());
            });

            Test("Broadcast action to two receivers, where the first to subscribe waits for the second to complete", assert =>
            {
                var dispatcher              = new AppDispatcher();
                DispatchToken token         = null;
                var secondReceiverProcessed = false;
                dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token);
                    assert.Equal(secondReceiverProcessed, true);
                });
                token = dispatcher.Receive(action =>
                {
                    secondReceiverProcessed = true;
                });
                dispatcher.Dispatch(new SomethingHappened());
            });

            Test("Broadcast action to two receivers that WaitFor each other - expect circular dependency failure", assert =>
            {
                var dispatcher       = new AppDispatcher();
                DispatchToken token2 = null;
                var token1           = dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token2);
                });
                token2 = dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token1);
                });
                assert.Throws(() => dispatcher.Dispatch(new SomethingHappened()), "Dispatch should throw in this case");
            });

            Test("Broadcast action to three receivers where the first waits on the third, the second waits on the first and the third waits on the second - expect circular dependency failure", assert =>
            {
                var dispatcher       = new AppDispatcher();
                DispatchToken token3 = null;
                var token1           = dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token3);
                });
                var token2 = dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token1);
                });
                token3 = dispatcher.Receive(action =>
                {
                    dispatcher.WaitFor(token2);
                });
                assert.Throws(() => dispatcher.Dispatch(new SomethingHappened()), "Dispatch should throw in this case");
            });
        }