jonas
Ultra Cool Member
- Reaction score
- 47
Task: Implement the Warcraft 3 event engine in C# or Java in a type safe, cohesive way, with low coupling
Problem: Different events have different data, so you need a way to distinguish between different events, handlers for different events, etc.
Slang:
interface IEvent (all events are objects of types that implement this interface)
interface IEventListener<E> where E : IEvent { void Handle(E event); }
or
interface IEventListener { void Handle(IEvent event); }
(listens to events of a specific type)
class Dispatcher { void Register???(IEventListener???); void Dispatch(IEvent e); }
(can register event listeners and broadcast events in an efficient manner).
Known Non-Solutions:
Problem: Different events have different data, so you need a way to distinguish between different events, handlers for different events, etc.
Slang:
interface IEvent (all events are objects of types that implement this interface)
interface IEventListener<E> where E : IEvent { void Handle(E event); }
or
interface IEventListener { void Handle(IEvent event); }
(listens to events of a specific type)
class Dispatcher { void Register???(IEventListener???); void Dispatch(IEvent e); }
(can register event listeners and broadcast events in an efficient manner).
Known Non-Solutions:
- Cluttering the event type with all the accessors (violates type safety of the event)
- Having a generic IEventListener<E> where E : IEvent type (then the dispatcher needs ListenersE1 : List<IEventListener<E1>>, ListenersE2 : List<IEventListener<E2>>, ..., because you can't mix instances of generics in a list - and whenever you create a new event, you have to change the code of the dispatcher in trivial ways)
- Having IEvent with no accessors, IEventListener with method Handle(IEvent e) (because you lose type safety of the event, and you need to type check and cast inside of the Handle())
- Having Handle<E>(E event), (because in the implementation of Handle you can't really know which type the event really is, so you can't access its fields etc.)
- Implementing one HandleE method for each event type, because then whenever you want to add a new event you have to touch the IEventListener interface (or better, make it an abstract class with default No-Op behaviours; otherwise you have to touch all the implementations as well)
- Having Handle<E>(E event) and checking E at compile time with static if, implementing it as a no-op in "wrong" types
- Allowing mixed generics in a list, and comparing the types
- Using types like enums
- ...
Last edited: