Vorab: Das Konzept der virtuellen Methoden hat nichts mit dem Konzept von virtuellen Methoden in objektorientierten Sprachen zu tun!
Eine Virtuelle Methode in iPlus ist im Grunde genommen eine konfigurierbare, serialisierbare und persistierbare Parameterliste, die einer richtigen .NET-Methode beim Aufruf übergeben wird. Wie beim Konzept der überladenen Methoden in .NET (dass Methodennamen zwar gleich benannt werden können, jedoch die Parameteranzahl variieren kann) können verschiedene Parameterlisten vorliegen.
Diese Parameterlisten müssen einen eindeutigen Namen haben und können per ACUrlCommand mit Ihrem "virtuellen Namen" aufgerufen werden - daher der Begriff "virtuelle Methode". Das iPlus-Framework weiß jedoch an welche tatsächliche .NET-Methode diese Parameterliste übergeben werden muss. Diese .NET-Methode muss dann intern so implementiert sein, dass sie mit diesen unterschiedlichen Parametersätzen arbeiten kann.
Virtuelle Methoden werden überwiegend in den Ableitungen der Klasse PAProcessFunction verwendet. PAProcessFunction's sind Klassen die nach dem ISA-S88-Standard implementiert sind und einen Zustand haben. Der Zustandsautomat startet wenn die PAPocessFunction über die asynchrone Methode Start gestartet wird (Virtuelle Methoden können ebenso auch bei synchronen Methoden verwendet werden. Ausserdem können asynchrone Methoden auch synchron verwendet werden). Die Start Methode kann entweder direkt über die GUI oder per Workflow gestartet werden. Das besondere an Workflows ist, dass sie diese Parameterlisten (virtuelle Methoden, Klasse ACMethod) in persistierender Form vorliegen haben und an die Start-Methode der PAProcessFunction delegieren können, wenn der Programmablauf an die entsprechende Stelle kommt. Die Parameterwerte dieser virtuellen Methoden können von Endanwender selbst editiert und im Workflow persistiert werden.
Die Start-Methode hat folgende Signatur:
[ACMethodAsync("Process", "en{'Start'}de{'Start'}", (short)MISort.Start, false)]
public virtual ACMethodEventArgs Start(ACMethod acMethod)
Die Klasse ACMethod besteht im Wesentlichen aus drei Eigenschaften:
Name | Beschreibung |
---|
ACValueList ParameterValueList | Diese Liste dient zur Speicherung der Parameter, mit der die Start-Methode umgehen kann (bzw. eine andere asynchrone Methode, die einen Parameter vom Typ ACMethod besitzt). Der Typ ACValueList ist eine Liste von ACValue. ACValue wiederum besitzt zwei wichtige Eigenschaften: - string ACIdentifier: Eindeutiger Name (ID) des Parameters
- object Value: Der eigentliche Parameterwert
|
---|
ACValueList ResultValueList | Diese Liste beinhaltet die variablen Rückgabewerte wenn die Start-Methode (bzw. eine asynchrone Methode) Ihre Arbeit erledigt hat. |
---|
string ACIdentifier | Der "virtuelle Methodenname". Der virtuelle Methodenname muss für die Start-Methode (bzw. eine asnychrone Methode) eindeutig sein. D.h. Wenn eine asynchrone Methode mit unterschiedlichen Parametersätzen arbeiten soll, dann müssen die ACIdentifier auch unterschiedlich sein. |
---|
Woher weiß nun die Start-Methode bzw. eine .NET-Methode mit dem ACMethod-Parameter, welche virtuelle Methoden es gibt und wo werden sie deklariert?
Damit eine virtuelle Methode bekannt ist muss sie im statischen Konstruktor registriert werden indem die statische Methode ACMethod.RegisterVirtualMethod aufgerufen wird:
ACMethod.RegisterVirtualMethod(typeof(PAFMixing), "Start", CreateVirtualMethod("Mixing", "en{'Mixing On/Off'}de{'Mischen Ein/Aus'}", typeof(PWMixing)));
Die Methode RegisterVirtualMethod hat drei oder vier Parameter:
Name | Beschreibung |
---|
Type typeOfACComponent | Typ der Klasse zu der die virtuelle Methode gehört (wo sie deklariert wurde und bekannt ist). |
---|
string assemblyMethodName | Name der .NET-Methode die mit der virtuellen Methode umgehen kann. Damit weiß das iPlus-Framework welche .NET-Methode aufgerufen werden soll um die virtuelle Methode (in dem Sinne die Parameterliste) übergeben zu können. |
---|
ACMethodWrapper acMethodWrapper | Diese Klasse ist im Prinzip eine Metabeschreibung der virtuellen Methode. Sie speichert zum einen eine Instanz der ACMethod selbst. Diese Instanz wird als Kopiervorlage verwendet, wenn ein neuer Parametersatz benötigt wird um einen neuen Methodenaufruf auf der .NET-Methode ausführen zu können. Zum anderen enthält Sie eine Übersetzungstabelle, die verwendet wird wenn die Parameterliste an der Oberfläche angezeigt wird, um den Parameter ausführlicher in der Sprache des Endbenutzers beschreiben zu können. |
---|
Type pwClass | Typ der Workflowklasse, die ebenfalls diese virtuelle Methode mit Ihrer Parameterliste kennt. |
---|
Im Code-Beispiel oben wird die Instanz des ACMethodWrapper durch den Funktionsaufruf CreateVirtualMethod(...) übergeben, weil dies zum einen aufgrund der Komplexität der Klasse deklarativ schwer möglich ist und zum anderen den Code unleserlich machen würde.
Schauen wir uns jetzt die CreateVirtualMethod-Methode etwas genauer an, um besser verstehen zu können wie die ACMethodWrapper-Instanz erzeugt wird:
Wenn Sie aufgepasst haben, werden Sie sich Fragen was ist mit den Rückgabewerten? Müssen diese etwa nicht in der ResultValueList stehen und ebenfalls bekannt gegeben werden?
Richtig, die ResultValueList wurde nicht deklariert, weil die Methode "Mixing" einfach keine Rückgabewerte hat.
Was glauben Sie - in welchen Fällen könnte denn ein Mischer einen Rückgabewert haben wenn man sich einfach eine Küchenmaschine vorstellt? Was würde denn passieren wenn man einen Teig eine sehr lange Zeit in einer Küchenmaschine rühren bzw. kneten würde?
Richtig, er würde sich durch die mechanische Reibung erwärmen - und schon haben wir auch einen Rückgabewert gefunden: "Temperatur".
Gibt es eigentlich technisch gesehen (bezüglich der Ansteuerung eines Rührwerks) einen Unterschied ob ich eine Küchenmaschine lange oder nur ganz kurz einschalte?
Nein, in beiden Fällen muss der Motor mit Spannung versorgt werden. Daher ist die technische Umsetzung die selbe.
Wenn Sie nun gut aufgepasst haben haben Sie die Lösung schon gefunden und das eigentliche Prinzip und den Vorteil der virtuellen Methode verstanden:
Wir definieren einfach eine weitere virtuelle Methode z.B. "MixingTemperature" mit der die Start-Methode auch arbeiten kann, jedoch muss Sie in diesem Fall noch die erreichte Temperatur beim ausschalten des Mischermotors der Küchenmaschine ermitteln und zurückgeben.
Wir fügen einen weiteren Aufruf im statischen Konstruktor hinzu:
ACMethod.RegisterVirtualMethod(typeof(PAFMixing), "Start", CreateVirtualTemperatureMethod("MixingTemperature", "en{'Mixing Temp.'}de{'Mischen Temp.'}", typeof(PWMixing)));
Die Implementierung der CreateVirtualTemperatureMethod sieht folgendermaßen aus:
Wenn wir nun die beiden Methoden CreateVirtualTemperatureMethod und CreateVirtualMethod vergleichen, fällt uns folgende Gemeinsamkeit auf:
Beide besitzen den Parameter "Speed"!
Die Start-Methode kann nun so abstrakt programmiert werden, dass Sie in beiden Fällen den Parameter "Speed" gleich behandelt.