/**------------------------------------------------------------------------------------------------ @modifies Obj @brief Creates a singleton out of any class. -------------------------------------------------------------------------------------------------*/ uses "reflection", "array"; /*------------------------------------------------------------------------------------------------*/ class modifies Obj { directive Hookable() { eval(" class modifies ${Class.name(self)} { static array hookers; static function addHooker(void hooker, array events) { string name = Class.name(hooker); events.each() using (event) { if (!.hookers.keyExists(event)) { .hookers['' + event] = []; } .hookers['' + event]['' + name] = hooker; }; } static function removeHooker(void hooker) { array events; .hookers.eachWithIndex() using (event, index) { events.push(.hookers.getName(index)); }; .removeHooker(hooker, events); } static function removeHooker(void hooker, array events) { string name = Class.name(hooker); events.each() using (event) { if (.hookers.keyExists(event)) { .hookers['' + event] = .hookers['' + event].subtract([name => '']); } }; } function callHooker(string event, array with) { array args = arguments(); if (!Hookable.hookers.keyExists(event)) { return with; } Hookable.hookers['' + event].each() using (hooker) { object hookerClass = new Class(hooker); object hookerFunction = hookerClass.getFunction(event); monitor { with = hookerFunction.exec(with); } handle (error) { object request = new Request(); request.print('' + error.num); } }; return with; } }"); } } /*------------------------------------------------------------------------------------------------*/ class Hookable { [Hookable]; function doSomething() { object request = new Request(); string output = "I don't know what to do!"; array with; // We need a hooker! with = .callHooker("doSomething", [output]); request.print(with[0] + "
"); } } /*------------------------------------------------------------------------------------------------*/ class Hooker { static constructor() { } //static function doSomething(array with) { static function doSomething() { with[0] = "I know what to do!"; // Don't want to handle this anymore! Hookable.removeHooker(self); return with; } } /*------------------------------------------------------------------------------------------------*/ object hooker = new Hookable(); Hookable.addHooker(Hooker, ["doSomething"]); hooker.doSomething(); hooker.doSomething(); /*------------------------------------------------------------------------------------------------*/