Multiple Observers of an Event

Thanks Ian, there are also times when a simple solution is best. The problem is I have the OO skills but not the Xojo skills just yet (I’ve only been working with Xojo for a few weeks).

Pair looks like exactly what I want; thanks for the tip!!! I think I will improve Notifier syntax using Pairs instead of Dictionaries before extensively using it. I have already modified Notifier to always send the subject to the handler along with any arguments which, seemed sensible.

I’ve now updated Notifier to support better syntax. As before you can download it from here.

You can now trigger notifications without arguments like this…

Notifier.trigger(self, "changed")

or with arguments like this…

Notifier.trigger(self, "ageChanged", "age": myAge)

and observe notifications like this…

Notifier.when(aPerson, "ageChanged", self, "updateAge")

You define a subject’s supported notifications by implementing the NotifierSubject interface and its supportedNotifications method like this…

dim notifications as Dictionary = new Dictionary notifications.value("changed") = new Notification notifications.value("ageChanged") = new Notification("age" : 0) return notifications

In the example above the changed notification has no arguments, the ageChanged notification as one argument. If this argument is not sent when it is triggered, the default value of 0 will be used.

Many thanks for all your comments and help. If anyone uses this and finds an issue, please let me know!

Interesting read. Thanks for sharing Chris & Ian.

I forgot to say, I usually get around this problem by simply defining a bunch of String constants in a module to hold the names of the events that I’m using, reduces mis-naming problems and allows for autocomplete. The module is usually called “Events” so that I can namespace the events and call them with Events.LOGIN_REQUEST or Events.kLoginRequest depending on the project’s naming conventions.

Hi Ian,

Yes constants are a good idea for auto completion. I wanted “supportedNotifications” to be a class method (sorry, shared method) as that is really where it belongs. But it seems Xojo interfaces don’t let you define shared methods and I felt the policing was more important than the correct placement.

Great job so far, this looks very cool. One critique though. You are using the type variant in a lot of your methods. This should be changed to object so that only objects can register to receive notifications, and not intrinsic types such as strings, integers, etc which will lead to hard to track down nilobjectexceptions. So the method

Shared Sub when(subject as NotifierSubject, notificationName as String, observer as Variant, methodName as String)

should be

Shared Sub when(subject as NotifierSubject, notificationName as String, observer as OBJECT, methodName as String)

and a few other will need to be changed as well.

To see what I mean, in the open event of the window in your example, change the line:

Notifier.when(App.guy, "ageChanged", self, "updateAge")


Notifier.when(App.guy, "ageChanged", 1, "updateAge")

The compiler will allow 1 to be entered and will compile because a 1 is acceptable with a variant parameter, but it is not what you want and will cause a nilobjectexception when you try to use introspection on it.

Many thanks Jason - my newness to Xojo shining through! I’ll correct and update.

I’ve now made the changes recommended by Jason (thanks again Jason).

I’ve updated the project. As a reminder you can download it here.

No problem. In case you weren’t aware, the use of variants is generally discouraged unless you really don’t care about what you are getting. It is recommended that whenever possible you specify the type as narrowly as possible so the compiler can assist you.

[quote=112798:@Chris Copleston]I’ve now made the changes recommended by Jason (thanks again Jason).

I’ve updated the project. As a reminder you can download it here.[/quote]

does the link valid?? I can’t open it.

[quote=112320:@Ian Jones]I’m a little late in seeing this discussion, but sometime ago I created a very simple synchronous event bus that might be of use to those interested in this area. It’s not a perfect fit for the discussed problem because you have to use a very specific method (implemented as an “Extends” on Object) to raise events rather than use the built in RaiseEvent, but for simple projects it works quite well.

There are a couple of example projects too…[/quote]

do you have a benchmark?