Tinkerforge/generators — pull request #14 by NobodysNightmare (2012-05-31 14:03:14+00:00)
Title: Eventbased callbacks

A month ago I proposed with Issue #7 to do the callback-handling via .NET-Events.
Today I made the neccessary changes, as I needed them for my current application.

I will explain what I did, what the benefits are, which caveats there are and what I did not do in favour of better backwards-compatibility but could do in favour of the more natural .NET-Solution.

What does change?
==============
All device-callbacks (global enumerate callback excluded) are now accessable as events, this means attaching to the Temperature-callback of a Temperature-Bricklet now looks like this:
````
myBricklet.Temperature += MyCallback;
````
detaching a previously registered callback is also possible:
````
myBricklet.Temperature -= MyCallback;
````

For all other purposes usage is basically the same.

The old RegisterCallback-method still works, but is marked as Obsolete.

Benefits
======
- multiple handlers per callback are possible (this is extremely good with bricks like the Servo-Brick, where you might want to have one PositionReached-handler per servo, not per Servo-Brick)
- type-checking is done at compile-time (whereas RegisterCallback(...) can only do runtime-checking)
- It is the natural C#/.NET-Way of doing callbacks (the previous way is not intuitive)

Caveats
======
As the name of the Delegates needed to be changed, old Code will break here:
````
myBricklet.RegisterCallback(new BrickletHumidity.Humidity(WriteConsoleHumidity));
````
because the delegate is now called HumidityEventHandler.

Why was that neccessary?
I think I could have let the name "Humidity", but as this is the most senseful name for the Event itself there would have been great confusion to what BrickletHumidity.Humidity refers (programmer-confusion, for the compiler this should be unambigious).

Short story: This caveat could be eliminated, but the costs in terms of understandability of the code are quite high.

Another caveat is, that calling the RegisterCallback-method with an empty callback previously lead to the old callback being removed. As RegisterCallback now internally uses the event-mechanism this implementation-detail does not hold anymore.

In the end both caveats concern backwards-compatibility, I don't think that there are weaknesses besides that.

.NET-Conventions
=============
There are some conventions on raising events in .NET, link: http://msdn.microsoft.com/en-us/library/wkzf914z(v=vs.80).aspx

I did not follow all of them to ease code-migration, however you might say that it is worth to follow all of them, because its just worth it.

The conventions are basically:
1. The delegate should be named EventNameEventHandler
2. events should be raised from a protected method called OnEventName
3. The delegates should accept the parameters (object sender, EventNameEventArgs eventArgs)

I did obey point 1 and 2. Explanation for Point 2: This basically allows subclasses of a device to access the event without registering for it.

Point 3 would have lead to a massively breaking change, as all callback-handlers would have had to be changed (Whereas now you only need to update callback-registration). However, for the C-Bindings a user already requested to be able to connect Multiple IO-Bricklets to the same callback and to be able to tell, which Bricklet raised the callback. This is exactly the purpose of the sender-argument from the .NET-conventions.

Further Questions?
==============
If there are further questions regarding .NET-Events or regarding some decisions I made feel free to ask/discuss.

Side Note
--------------
This Request also includes the changes from my other pull request, this came out of convenience for me, you might want to simply close the other pull request or pull it anyway as those commits should then just fade away from this pull request.