Day 9.2 – EventAggregator

After the ModuleCatalog was working again I decided to get something done with Prism’s EventAggregator.

Basically the EventAggregator’s purpose is to redirect “messages” and work like the Publish/Subscriber pattern.
Say for an instance that want to send a letter to a friend. You write the friend’s name and address on the letter and gives it to the mailman – later the letter shows up at your friends house. You can see the EventAggregator as the mailman.

With the Publish/Subscriber system we create an event we publish – in my project I have a “Start Motor”-event.
Then I have a module which controls the motor. I subscribes to the “Start Motor”-event. So whenever the “Start motor”-event is called, the MotorControlModule runs whatever it needs to do to get the motor going.

“Well that’s a 1-1 relationship, I could just have create an object” – sure could. But now it gets fancy!

Each time I publish my “Start Motor”-event I want to log it in my database.
This means I subscribe to the “Start Motor”-event in my LoggingModule and stores the data I have sent.

Perhaps I would like to change something in another part of my GUI in another module.
Subscribe “Start Motor”-event and it’s done.

“Is it hard?”
Well, it hard than it looks but easier than it sounds… (read it again and accept it).

First we need to create the event. Prism does it as follow (easy part):

  public class StartMotorEvent: CompositePresentationEvent<Motor>{}

  public class Motor
  {
    public bool Activated { set; get; }
    public int Speed { set; get; }
  }

We just created an event, called “StartMotorEvent” and said we would give it a ‘Motor’-object as parameter.

Then we publish the event when we hit the button:

        private void ButtonClick()
        {
            var motor = _container.Resolve<Motor>();
            motor.Speed = 100;
            motor.Activated = true;

            _eventAggregator.GetEvent<StartMotorEvent>().Publish(motor);
        }

First we get an instance of the Motor-class – that’s how the Unity container does this.
Then we set a desired speed and activates the motor.
That is how we want the motor to work – publish it:
Take the EventAggregator and find you event and publish it with the Motor-object

Subscribe to the event – here it gets “tricky”:

    public class MotorController
    {
      private readonly IEventAggregator _eventAggregator;
      private SubscriptionToken subscriptionToken;

      public MotorController(IEventAggregator eventAggregator)
      {
        _eventAggregator = eventAggregator;
        SubscribeToEvents();
      }

      // Called by the constructor
      private void SubscribeToEvents()
      {
        var activateMotorEvent = _eventAggregator
            .GetEvent<StartMotorEvent>();

        //If, for some reason, the constructor is called twice we 
        //unsubscribe so we won't do everything double.
        if (subscriptionToken != null)
        {
          activateMotorEvent.Unsubscribe(subscriptionToken);
        }

        subscriptionToken = activateMotorEvent
            .Subscribe(ActivateMoterHandler, 
                       ThreadOption.BackgroundThread, 
                       false);
      }
      
      public void ActivateMoterHandler(Motor motor)
      {
        //Activation of motor
      }
    }

Big mouthful so step for step:
When the class is resolved (in its module) the constructor is called. This calls SubscribesToEvents() which will first get an instance of the event, check if token that holds the event is not null (if not the constructor is called twice and we don’t want double work here), and subscribes to the event.
The subscribe function has a few overloadings but this shown takes a method to do something (what we actually wants done), which thread it must be run in (BackgroundThread, UIThread, PublisherThread), and if it is to be kept alive (which some website strongly advise not to do).

It is also possible to add a filter, so only certain values activate the motor, but it is not shown here.

… yeah, that’s about it.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>