Driver Model
How does AgateLib work on different platforms? The answer is simple really, thanks to powerful reflection capabilities in the .NET standard library.
AgateLib has several abstract classes located in AgateLib.ImplementationBase which must be inherited from by a driver. The three main subsystems (Display, Audio and JoystickInput) have abstract classes which behave as a class factory to create their own concrete implementations of these abstract base classes.
When the Agate library is initialized, it searches the directory of the executing file for other DLL's. Each DLL it finds, it checks for a class extending AgateDriverReporter. When it finds one, AgateLib instantiates it and asks it what classes in the library provide implementations for the AgateLib subsystems. The best one of these is chosen and used for running the graphical engine (or audio or input). New drivers can be added to an existing program without recompiling it. Thanks to Mono's ability to load and execute MSIL, one can compile a game into a binary executable with Microsoft Visual Studio, for example, and copy it to a Mac OS X machine, drop in appropriate Mac OS X drivers and run the application. All of this happens behind the scenes.
If multiple drivers are present, Agate will choose the best available one. Agate can also show a dialog to the user asking them which drivers to choose. This is useful for debugging purposes. This also allows a single distribution to be constructed for all platforms just by including the drivers for each platform.