CSharpMessenger Extended

Author: Magnus Wolffelt (with Rod Hyde quotations), Julie Iaccarino (Callback return extensions, cleanup, covariance, slowdown, then speedup)

Description
This tries to be a programmer-mistake-resilient delegate-based event system for C#. It uses generics to achieve static typing. Based on and inspired by Rod Hyde's CSharpMessenger, please refer to it for more usage details. The use of generics means that parameters can be of any type and are not restricted to subclasses of a special Message class - if a callback only needs a float then supply it with a float.

Usage
The main difference in usage from Hyde's implementation, is that with this messenger you can not have several events with same name, but different parameter signature. So for example, if you register a listener for "myEvent" with no parameters, and later try to register an event listener for "myEvent" that takes a float parameter, an exception will be thrown. Furthermore, there's an optional MessengerMode that allows for requiring at least one listener to exist when broadcasting an event. Generally, this Messenger will throw a lot of exceptions as soon as the programmer makes mistakes. Not all potential errors can be covered, but it tries to be strict in order to prevent silent, undetected bugs.

Registering a callback return
In some cases, a return value will be desired when sending out a message. Callback returns act in this capacity, allowing a broadcaster to receive a return value for every subscriber listening to the event type.

The listener might look like this:

Where the  parameter on the AddListener function declares a return type. It is still possible to use one, two, or three types for parameters on the main Messenger class.

The broadcast may look like this:

It's important the signature matches the listener and the broadcaster.

Warning
RemoveListener should always be called on messages when loading a new level. Otherwise many MissingReferenceExceptions will be thrown, when invoking messages on destroyed objects. For example: 1. We registered a "speed changed" message in a Level1 scene. Afterwards the scene has been destroyed, but the "speed changed" message is still pointing to the OnSpeedChanged message handler in the destroyed class. 2. We loaded Level2 and registered another "speed changed" message, but the previous reference to the destroyed object hasn't been removed. We'll get a MissingReferenceException, because by invoking the "speed changed" message, the messaging system will first invoke the OnSpeedChanged handler of the destroyed object.

Messenger Mode
Initially DEFAULT_MODE is set to require listeners, so you need to explicitly say a listener is not required when broadcasting. If preferred, change DEFAULT_MODE to not require listeners, so you must explicitly say when a listener is required:

Code
There are two files, Messenger.cs and MessengerUnitTest.cs. The last one is not required for usage.