Event handling: bessere Alternative als Reflection?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

DivineDominion

Betreff: Event handling: bessere Alternative als Reflection?

BeitragMo, Apr 29, 2019 21:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe überlegt, ob ich direkt GameEvents mitsamt EventHandler usw. nutzen soll, weil es so viele Beispielprojekteim Internet tun.

Eigentlich hätte ich aber lieber etwas einfacheres. Da die aktuelle bmax-ng Version 0.99 noch keine enums unterstützt, stelle ich mir das mit den Event Namen auch nervig vor.

In Ruby habe ich ein einfaches Pattern kennengelernt, bei dem man das Objekt fragt, ob es "on_something_did_change" implementiert. Wenn ja, wird der Callback aufgerufen. Das lässt sich in BlitzMax mit brl.reflection ja auch machen:

BlitzMax: [AUSKLAPPEN]

Type EventDispatcher
Field listeners:TList = New TList

Method AddListener(obj:Object)
Self.listeners.AddLast(obj)
End Method

Method Fire(eventName:String, source:Object, payload:Object = Null)
Local callbackName:String = "On" + eventName
For Local listener:Object = EachIn Self.listeners
Local callback:TMethod = TTypeId.ForObject(listener).FindMethod(callbackName)
If callback
If callback.ArgTypes() = Null Or callback.ArgTypes().Length = 0
callback.Invoke(listener)
Else If callback.ArgTypes().Length = 1
callback.Invoke(listener, [source])
Else
callback.Invoke(listener, [source, payload])
End If
End If
Next
End Method
End Type


Der Dispatcher nimmt dann String-basierte Events an und leitet die weiter, wenn registrierte Listener ein e Callback-Methode implementieren, die "On"+EventName heißt: Zu "PlayerDidWin" wird "OnPlayerDidWin()" aufgerufen.

Beispiel:

BlitzMax: [AUSKLAPPEN]

Type Bar
Field x% = 0
End Type

Type Foo
Method OnBarDidChange(bar:Bar, changes:Int[])
Print("Changed to: " + String(bar.x) + ", "+String(changes[0])+"/"+String(changes[1]))
End Method
End Type

Type Baz
Method OnBarDidChange(bar:Bar)
Print("Changed in Baz to: " + String(bar.x))
End Method
End Type

Local bar:Bar = New Bar()
bar.x = 1234
Local dispatcher:EventDispatcher = New EventDispatcher()
dispatcher.AddListener(New Foo())
dispatcher.AddListener(New Foo())
dispatcher.AddListener(New Baz())
dispatcher.Fire("BarDidChange", bar, [12, 34])

' Output:
' Changed in Foo to: 1234, 55/66
' Changed in Foo to: 1234, 55/66
' Changed in Baz to: 1234


Man kann Arrays als Daten ("payload") übergeben, oder auch nix; und die konkreten Callback-Methoden können Daten ignorieren, wenn sie keine weiteren Parameter akzeptieren.

Habt ihr so einen Event Handler selbst schon benutzt? Von der vergleichsweise schlechten Performance abgesehen (spielt für mich keine Rolle, weil die Listener nicht in jeder Frame der GameLoop Events bekommen), habt ihr andere Lösungen, die ihr lieber mögt? Warum?
christian.tietze@gmail.com - https://christiantietze.de
macOS

Jolinah

BeitragMo, Mai 13, 2019 19:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, ich hatte das hier mal gepostet, aber nutzt auch Reflection:
https://www.blitzforum.de/foru...hp?t=39969.

Ist im Prinzip sehr ähnlich, wobei dein EventDispatcher eher schlanker und einfacher ist. Ich wollte nur als Alternative darauf hinweisen.
Mit BlitzMax hat man ansonsten nicht viel mehr Möglichkeiten denke ich.. Smile

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group