Probleme mit einem Event-Manager
-
class EventManager : public IUnknown { private: /// \brief Constructor EventManager(); public: /// \brief Deconstructor virtual ~EventManager(); /// \brief Accessor for the Singleton. static EventManager& getInstance(); /** \brief Registers a new Event * \param id The Event-ID to Register. */ void registerEvent(const int id); /** \brief Registers a new Receiver of an Event * \param event A reference to an event. */ void registerReceiver(const Event& event); /** \brief Unregisters a complete Event-ID * \param id The ID to remove. */ void unregisterEvent(const int id); /** \brief Unregisters the Receiver of an Event. * \param event A reference to an Object of Event. */ void unregisterReceiver(const Event& event); /** \brief Notifies the Manager, that an Event wants to be fired. * \param id The Event-Id. */ void notify(const int id); private: // Initial List std::list< std::list<Event> > m_eventList; // No copy EventManager(const EventManager&) {} EventManager& operator=(const EventManager&) { return *this; } };Das ist jetzt mal meine Vorstellung eines simplen Event-Managers.
Die Idee dahinter:
Jede Klasse kann ein Event anmelden und jede Klasse kann sich als Empfänger für eine Event-ID anmelden. Wenn jetzt eine ID noch nicht eingetragen ist, wird eine neue Liste dafür angelegt. So hat quasi das Event ID_FOOBAR eine eigene Receiver-Liste und das Event ID_MYEVENT genauso. Sollte Zeit sparen beim suchen der Empfänger.
Die Klasse Event enthält eine virtuelle Funktion die von einem Empfänger überschrieben werden muss, um das Event zu erhalten. (virtual void onEvent();)class RPGLIB_CALL Event : public rpgLib::IUnknown { public: /// \brief Constructor Event(); /** \brief Constructor * \param id The id to use. -1 indicates an invalid id. */ Event(const int id = -1); /// \brief Deconstructor virtual ~Event(); /// \brief Executes the Event. virtual void onEvent(){} /// \brief Returns the ID of the Event. const int& getEventId() const; /** \brief Sets the Events ID. * \param id The id to use. -1 indicates an invalid id. */ void setEventId(const int id); protected: int m_id; };Jetzt komm ich nur in Schwierigkeiten dabei. Und zwar die Übergabedaten. Erst dachte ich daran, die Klasse Event als Template zu realisieren (Unbekannt wäre T für die Daten), aber da hab ich wieder das Problem, dass ich sie dann nicht als Parameter verwenden kann, ohne den EventManager auch als Template einzubauen.
template<classname T> class Event : public IUnknown { public: /// \brief Constructor Event(); /** \brief Constructor * \param id The id to use. -1 indicates an invalid id. */ Event(const int id = -1); /// \brief Deconstructor virtual ~Event(); /// \brief Executes the Event. virtual void onEvent(const T& data){} /// \brief Returns the ID of the Event. const int& getEventId() const; /** \brief Sets the Events ID. * \param id The id to use. -1 indicates an invalid id. */ void setEventId(const int id); protected: int m_id; T m_data; };Und das ist ja nicht der Sinn der ganzen Geschichte.
Vllt geh ich ja auch komplett falsch ran, aber ich möchte das ganze so einfach wie möglich halten und ohne Boost::Signals... wenn möglich.
Jemand eine Idee?
rya.
-
Wenn jedes Event von der Basisklasse 'Event' erbt, kann es doch selber die Daten verwalten: Erzeugung mittels Konstruktor und Auslesen der Parameter aus der Methoden onEvent.
Alternativ kannst du eine Basisklasse für die Parameter anlegen und mußt dann nur in 'onEvent' auf den speziellen Typ casten.
P.S. Wenn du mit Polymorphie arbeitest, mußt du Zeiger auf die Events in der Manager-Klasse verwalten: std::list< std::list<Event*> > m_eventList
-
Danke für den Denkanstoß. Hab jetzt die Methode mit der Basisklasse genommen :).
http://rpglib.googlecode.com/svn/trunk/src/EventManager.cpp
Die Klasse Event gibts dafür nicht mehr:
http://rpglib.googlecode.com/svn/trunk/include/Event.hDafür gibts jetzt die Klasse EventReceiver die eben das Event erhält. Der Code um ein Event anzumelden und auszühren ist relativ einfach:
// Übergabewerte für das Event class MyEventData : public IEventData { public: MyEventData(const rpgString& data) : IEventData(), m_data(data) { } const rpgString& getData() const { return m_data; } void setData(const rpgString& data) { m_data = data; } private: rpgString m_data; }; // Der Empfänger class MyEventReceiver : public EventReceiver { public: MyEventReceiver(const int id) : EventReceiver(id) { } virtual void onEvent(IEventData* data) { std::cout << "Event fired! Data: " << dynamic_cast<MyEventData*>(data)->getData() << std::endl; } }; int main() { MyEventReceiver *receiver = new MyEventReceiver(); MyEventData *data = new MyEventData("Hello Event"); // Event-ID anmelden EVENTMANAGER().registerEvent(rpgID_DEFAULT); // Event-Empfänger anmelden EVENTMANAGER().registerReceiver(rpgID_DEFAULT, receiver); // Feuert das Event EVENTMANAGER().notify(rpgID_DEFAULT, data); delete receiver; delete data; }Wenn noch jemand Verbesserungen hat, immer her damit

rya.