Das Notes Forum

Domino 9 und frühere Versionen => ND9: Entwicklung => Thema gestartet von: khing am 06.07.15 - 16:50:09

Titel: Suche Lösungsansatz für dynamisches Klassenmapping
Beitrag von: khing am 06.07.15 - 16:50:09
Hallo,

ich habe verschiedene kleine Klassen dich ich nur initialisieren möchte und darin immer die gleiche Funktion aufrufe z. B. so:
Code
Dim vObject = MeineKlasse1   'MeineKlasse2 usw.
Set vObject = New MeineKlasse1(vNotesDocument) 'Datentyp NotesDocument soll übergeben werden
Call vObject.Run()
Welche der Klassen aufgerufen wird, soll mittels eines Formular entschieden werden. Also steht dies erst zur Laufzeit fest.

Da ich ich davon ausgehe, dass die Anzahl dieser kleinen Klassen immer mehr werden, wollte ich mir ein Mapping ersparen. Mit der Funktion Execute bin ich leider auch nicht weiter gekommen, da diese keine Objekte zurückgibt. Nun kann ich sicher alle Klassen Public setzen und das Call vObject.Run() im Execute ausführen aber wäre auch nicht so schön  ::) (zumal die Klassen Public sein müssten).

Ich hoffe, dass ich mich einigermaßen verständlich ausgedrückt habe...  ;) Kennt ihr eine Möglichkeit das (besser) zu lösen?

Vielen Dank und schönen Feierabend.

Gruß Kristian
Titel: Re: Suche Lösungsansatz für dynamisches Klassenmapping
Beitrag von: MadMetzger am 06.07.15 - 19:36:34
Man kann in Lotus Script Vererbung, Polymorphie und eine Anlehnung an das Pattern Fabrikmethode (https://de.wikipedia.org/wiki/Fabrikmethode) für die Lösung deines Problems nutzen:

1. Schaffe eine Oberklasse zu deinen MeineKlasseX, nennen wir Sie MeineOberKlasse
2. In der Oberklasse erstelle eine Methode Run(), die nichts tut.
3. Deine Meine Klasse leitet von MeineOberKlasse ab und implementiert die Methode Run(). Wenn ich mich recht erinnere ging das etwa so (https://www.ibm.com/developerworks/lotus/library/ls-object_oriented_LotusScript):
Code
Class MeineKlasseX As MeineOberklasse
...
4. Für die dynamische Auswahl der richtigen MeineKlasse erstellst du dir eine Function, die dir kontextabhängig eine Instanz der richtigen Unterklasse zurückgibt. Das ist dann die Fabrikmethode, wie eingangs erwähnt.
Titel: Re: Suche Lösungsansatz für dynamisches Klassenmapping
Beitrag von: ERR am 05.08.15 - 15:08:29
Hallo Kristian,

per Execute ist es auch machbar. Im Internet gibt es diese Beispiele zu finden ("Dynamic Lotusscript"). Hier ist meine Umsetzung dazu.

Zuerst eine Scriptbibliothek anlegen (z.B. "libNewObj") und dort die zwei globale Variablen in Declarations definieren:

Code
Private vntFactories List As Variant
Public vntNewObj_factory As Variant

Dann diese Funktion in die Scriptblibliothek einfügen:

Code
Function fktNewObj( strClassName As String ) As Variant
	
	'Fehlerbehandlung
	On Error GoTo Error_Handler
	'
	'Variablendeklaration
	Dim strScript As String
	'
	'Prozedur
	If Not IsElement(vntFactories(strClassName)) Then
		strScript = |
Use "| & strClassName & |"
Sub Initialize
Set vntNewObj_factory = New | & strClassName & |Factory
End Sub
|
		Execute (strScript)
		Set vntFactories(strClassName) = vntNewObj_factory
	End If
	
	Set fktNewObj = vntFactories(strClassName).produce
	
e:
	
	Exit Function
	
Error_Handler:
	Set fktNewObj = Nothing
	
'... hier entsprechendes Error-Handling einfügen
	
	Resume e
End Function

In jeder deiner Scriptbibliotheken muss dann zusätzlich zu deiner Klasse eine weitere (Mini-)Klasse angelegt werden:
Code
Class MeineKlasse1Factory
	
	Function produce As Variant
		Set produce = New MeineKlasse1
	End Function
	
End Class

In der Maske oder auch z.B. einem Agent muss in den Options
Code
Use "libNewObj"

eingefügt werden und dann per Aufruf der Funktion fktNewObj verwendet werden:
Code
Dim strKlasse As String

' Variable mit dem Klassennamen setzen (in deinem Beispiel z.B. aus einem Feldwert)
strKlasse = "MeineKlasse1"

' neues Objekt zu der Klasse erzeugen
Set objMeineKlasse1 = fktNewObj(strKlasse)

' Methode der Klasse im Objekt aufrufen
Call objMeineKlasse1.Run()

Leider können keine Parameter direkt übergeben werden, aber das kann man umgehen, in dem man in der jeweiligen Klasse eine "Init"-Funktion anlegen und die dann per

Code
objMeineKlasse1.Init(doc, view, Param3, Param4, ...)

zuweist.

MFG
ERR