Using an event bus inside an application is pretty common. A very simple example could be decoupling the logic that sends notifications to the user in WPF from the ViewModels, without having to inject dependencies into the ViewModel. Although until now I had always written my own event bus, using Reactive Extensions turned out to be very interesting, useful, and simple. This would be an example of an event bus using RX:

public static class ReactiveEventBus {
    private static readonly Subject<object> messageSubject = new Subject<object>();

    public static void Send<T>(T message) {
        messageSubject.OnNext(message);
    }

    public static IObservable<T> AsObservable<T>() { return messageSubject.OfType<T>(); }
}

I found this code here.

The usual thing in an event bus is to have one mechanism to send events and another to subscribe to them. In this case, instead of enabling subscription, what it gives me is the ability to get an IObservable, where T is the type of the message I want to observe.

Applied to the notifications example, in the MainWindow (or wherever) I could add this code:

var subscription = ReactiveEventBus.AsObservable<GlobalMessage>().Subscribe(message => MessageBox.Show(message.Message));
Closed += (sender, args) => subscription.Dispose();

And that would let me send messages from any ViewModel (or anywhere else) with this code:

ReactiveEventBus.Send(new GlobalMessage("Hello!"));

It’s very important to remember the call to the subscription’s Dispose() to avoid problems releasing resources.

The interesting thing about the event bus giving me an IObservable is that, combined with RX, I can do more complex things in a very simple way, like:

ReactiveEventBus.AsObservable<ScopedEvent>()
    .Where(evt => evt.Scope == "Scope1")
    .Subscribe(evt => PUT YOUR CODE FOR Scope1 HERE);

ReactiveEventBus.AsObservable<ScopedEvent>()
    .Where(evt => evt.Scope == "Scope2")
    .Subscribe(evt => PUT YOUR CODE FOR Scope2 HERE);

As for whether it makes sense to use a property to determine the scope or whether it would be better to use an object of a different type, the answer is the usual one: it depends 😉

Some cases where I find it interesting are sending an event meant only for the UserControls showing a specific entity in an MDI interface, or making the scope of an event a specific window.