BoeseB
BoeseB

Reputation: 725

Translate CancelableEvent to RX

currently i try to get into thinking the Reactive Extensions way, by only send one way messages from components. But i still havent figuered out how to implement something with CancelableEventArgs that relies on the synchronous execution of the registered handlers into a solution that works with rx.

Example:

public void Delete()
{
    var deleteRequest = new DeleteServerRequest(_serverConfigurationMapper.Map(SelectedServer)); 
    _eventStream.Push(deleteRequest);
    if (!deleteRequest.Cancel)
        _serverConfigurationRepository.Delete(deleteRequest.Server);
}

In another class i register on the DeleteServerRequest and show a prompt so the user is able to cancel the deletion of the item.

_eventStream.Of<DeleteServerRequest>().Subscribe(
    req =>
      req.Cancel = DilaogResult.Yes != MessageBox.Show("Delte Server?", 
                                                       "Do you want to delete the server?",
                                                       MessageBoxButtons.YesNo))

How would i do something like this with only one directional messaging like in RX?

PS: The Delete method is the implementation of a command in a ViewModel, so i didn't want to bring UI-Framework code into it. The EventHandler is in a controller, that only should show and close the different windows and dialogs.

Upvotes: 0

Views: 41

Answers (1)

paulpdaniels
paulpdaniels

Reputation: 18663

Sure you can do this, just move the cancellation down stream.

_eventStream.Of<DeleteServerRequest>()
  .Map(req => {
    req.Cancel = DialogResult.Yes != MessageBox.Show("Delete Server?", 
                                                       "Do you want to delete the server?",
                                                       MessageBoxButtons.YesNo));
    return req;
  })
  .Filter(x => !x.Cancel)
  .Publish().RefCount()
  .Subscribe(x => _serverConfigurationRepository.Delete(x.Server));

I'm personally not a big fan of the "merge all events into a single stream" approach and although it is valid I would create a stream specifically for deletions and then wrap the request creation in it as well. This will also help remove side effects that are being pulled into the Observable during its operation. In which case Delete would look like

public void Delete()
{
    _deleteStream.Push(SelectedServer);
}

And the stream would look like:

_deleteStream
  .Map(selected => new DeleteServerRequest(_serverConfigurationMapper.Map(selected)))
      .Map(req => {
        req.Cancel = DialogResult.Yes != MessageBox.Show("Delete Server?", 
                                                         "Do you want to delete the server?",
                                                           MessageBoxButtons.YesNo));
        return req;
      })
      .Filter(x => !x.Cancel)
      .Publish().RefCount()
      .Subscribe(x => _serverConfigurationRepository.Delete(x.Server));

Upvotes: 1

Related Questions