Events
Wenn zur Unterstützung für eine .NET-Implementierung eine Basis-Assembly mit dem Werkzeug ExpEdge erzeugt wird, befindet sich in dieser Assembly für den zu implementierenden Baustein eine Klasse mit dem Namen des Bausteins. Diese Klasse befindet sich in einer Namespace, die aus dem Typ, der Anwendung und einer sog. Root-Namespace gebildet wird. Die Root-Namespace entspricht im Allgemeinen dem Namen der Assembly.
Wenn zum Beispiel eine Assembly TeamWiSE.TestCases
mit der EFUN
TC-OBJFLD-DLLCLR
aus der Anwendung SAMPLE
erzeugt wurde, enthält diese Assembly eine Klasse TeamWiSE.TestCases.Sample.Efun.TcObjfldDllclr
. Diese Namensgebung ist nicht zwingend, sondern lässt sich in gewissem Rahme bei der Generierung maßgeschneidert gestalten. Für Einzelheiten fragen Sie bitte bei Ihrem TAA-Administrator nach.
Die so erzeugte Klasse bietet die Basisklasse für die Realisierung des Bausteins. Um also gemäß dem vorigen Beispiel den Baustein TC-OBJFLD-DLLCLR
zu realisieren, wird in einem (bestehenden oder neuen) .NET-Projekt eine Referenz auf die Basis-Assembly gelegt, und eine von der generierten Klasse abgeleitete Klasse erzeugt. Die Namensgebung dieser Klasse ist frei gestaltbar.
Wichtig ist, dass diese Klasse und die von Ihnen erzeugte Assembly in den Ispc-Angaben des Bausteins eingetragen werden. Als auszulösende Methode wird von der TAA immer die Methode Execute
genommen, egal welche Angabe in der Ispc vorgenommen wurde. Insofern kann dieser Teil der Ispc leer bleiben.
namespace TeamWiSE.DllClrNative { using TeamWiSE.TestCases.Efun.Sample; class TC_OBJFLD_DLLCLR : TcObjfldDllclr {
Die Methode Execute
wird auf Basis des Bausteintyps unterscheiden, ob von einem Aufrufer und Übergabeargumenten ausgegangen werden soll, oder ob der Baustein als Einstiegsbaustein betrachtet werden muss. Die Implementierung wird dementsprechend mit Register/Unregister
oder mit Enter/Leave
umklammert. Optional kann der Execute
-Methode eine Zeichenfolge übergeben werden, die das Ergebnis von einem vorangehenden Prepare
war. Dann wird sich der Baustein als gehörend zu dem vorbereiteten Aufruf registrieren und ablaufen.
Um nun den Baustein zu implementieren, wird in der abgeleiteten Klasse eine oder mehrere Methode(n) der Basisklasse übersteuert. Folgende Methoden bieten sich an:
In der Regel genügt es, entweder die Methode RunImplementation
oder die Methoden für die einzelnen Operationen1) zu übersteuern. Grundsätzlich gilt, dass, wenn die Implementierung größtenteils gleich für alle Operationen ist, man die Methode RunImplementation
2) übersteuert. Wenn die Implementierung des Bausteins sich jedoch wesentlich pro Operation unterscheidet, empfiehlt es sich stattdessen die Einzelmethoden für die Operationen zu übersteuern.
Wenn man die Methoden für die einzelnen Operationen übersteuert, ist es i.d.R. nicht notwendig, auch RunImplementation
zu übersteuern, da die Implementierung in der Basisklasse für diese Methode bereits das laufzeitabhängige Ansteuern der Einzelmethoden vornimmt.
Falls eine passende Übersteuerung fehlt, wird das Auslösen der Methode Execute
zur Laufzeit eine Ausnahme NotImplementedException
aufwerfen.
In bestimmten Fällen kann es sich anbieten, sowohl RunImplementation
zu übersteuern, als auch alle oder bestimmte Operation<XXX>
-Methoden. Nachfolgend ein fortgeschrittenes Beispiel:
protected override void RunImplementation() { InitializeGeneralConnections(); try { switch (Operation.Active) { case OperationEnum.Durchfuehren: InitializeSpecialConnections(); OperationDurchfuehren(); break; default: OperationUdef(); break; } } finally { Cleanup(); } }
Zur Unterstützung der Implementierung bietet die Basisklasse diverse Methoden und Eigenschaften. Die Benutzung von IntelliSense® in Visual Studio® erleichtert das Auffinden solcher Funktionalitäten, wie das nachfolgende Bild zeigt:
Die in diesem Bild gezeigten Methoden sollten allerdings mit Bedacht benutzt werden. So ist die Methode Execute
aus Implementierungsgründen zwar sichtbar, sollte aber nicht aus der Implementierung heraus aufgerufen werden. Der Versuch, dies zu tun, wird mit einer Ausnahme InvalidOperationException
quittiert.
Für einige Bausteintypen können spezialisierte Basisklassen zugrunde gelegt werden. Derzeit werden folgende von TeamWiSE.Runtime.NativeSupport.Module
abgeleitete spezialisierte Klassen verwendet:
NTRY
Bausteine: TeamWiSE.Runtime.NativeSupport.ModuleNtry
WEBA
Bausteine: TeamWiSE.Runtime.NativeSupport.SessionModule
Die Basisklasse bietet als public
Eigenschaften die Zeichenfolgen Appl
, Type
und Name
an, mit der die entsprechenden Angaben zum Baustein in Großbuchstaben abgerufen (nicht verändert) werden können.
Außerdem steht ebenfalls public
die (nicht veränderbare) Eigenschaft IsRegistered
zur Verfügung, die angibt, ob sich der Baustein derzeit in einem registrierten Zustand befindet.
Die Eigenschaften Operation
, State
, Data
, Call
und Gevo
liefern jeweils eine dedizierte Klasseninstanz, die wiederum unterstützende Methoden und Eigenschaften für den jeweiligen Themenkomplex bietet. Die Details sind getrennt beschrieben. Man beachte, dass die Eigenschaft Call
nur dann verfügbar ist, wenn es für den Baustein eine nicht-leere Aufrufstruktur gibt.
public void Yield(ContainerControl parent, YieldStrategy.DisableKind disableKind)
Die Methode Yield
steht für die zwischenzeitliche Rückgabe der Kontrolle zum Aufrufer zur Verfügung.
public Boolean Register(String preparedToken); public Boolean Register(OperationEnum operation);
Im Falle einer vorbereiteten Bausteinoperation kann sich die Implementierung mit der von der Prepare
-Methode gelieferten Zeichenfolge registrieren. Zur Erleichterung der Buchführung besteht jedoch auch die Möglichkeit, dass sich der Baustein für die jeweilige Operation registriert, ohne dazu eine Token-Zeichenfolge zu besitzen. In diesem Fall wird die TAA versuchen ein passendes Token zu finden. Dabei werden allerdings nur solche gefunden, die im gleichen Prozess vorbereitet wurden.
Neben den bereits erwähnten Methoden Execute
, RunImplementation
und Operation<XXX>
stehen die Standard Object-Methoden MemberwiseClone
, GetType
, GetHashCode
und Equals
zur Verfügung. Die Methode ToString
liefert eine Zeichenfolge bestehend aus Anwendung, Typ und Name des Bausteins, jeweils durch Punkt getrennt.
Da die Basisklasse das Interface IDisposable
implementiert, steht auch die Methode Dispose
zur Verfügung. In der Basisklasse wird beim Dispose
sichergestellt, dass eine ggf. noch offene Registrierung des Bausteins durch Unregister
oder Leave
beendet wird.
Die Klasseninstanzen von den Bausteinen, die auf generierte Basisklassen basieren3), werden von der TAA Infrastruktur zur Wiederverwendung4) vorgehalten. Es liegt in der Entscheidung der TAA, wann eine solche Instanz aufgeräumt wird, spätestens ist das jedoch am Ende des Gevos oder des Prozesses der Fall. Um die in dem Baustein vorgehaltene managed und unmanaged Ressourcen freizugeben, kann die Implementierung die Dispose
-Methode überlagern.
protected virtual void Dispose(bool disposing)
Die Methode Dispose
folgt dem allgemeinen Dispose-Pattern. dabei gibt das Argument disposing
an, ob das Aufräumen von der IDisposable.Dispose
-Methode (true
) oder vom sog. Finalizer
(false
) verlangt wurde.
Im Allgemeinen besteht die Implementierung der Dispose
-Methode aus zwei Abschnitten. Im ersten Abschnitt werden die noch vorhandenen unmanaged Ressourcen freigegeben. Der zweite Abschnitt erfolgt nur dann, wenn nicht der Finalizer
sondern einen konkreten Dispose
verlangt wurde, der disposing
Parameter also true
ist. In diesem zweiten Abschnitt werden die noch vorhandenen managed Ressourcen freigegeben die entweder selbst IDisposable
sind, oder einfach viel Speicher verbrauchen.
Man sollte die Implementierung so wählen, dass die Dispose
-Methode mehrfach ausgeführt werden kann, ohne negativen Folgen5) in der Implementierung der Methode. Auch kann die Dispose
-Methode in unterschiedlicher Reihenfolge (mal false
/true
, mal umgekehrt) ausgeführt werden.
Events
Execute
übersteuert, sondern die Methode RunImplementation
. Die Methode Execute
wird vollständig in der Basisklasse implementiert und erledigt sämtliche Aufgaben wie Register/Unregister
und was sonst noch alles notwendig sein könnte.TeamWiSE.Runtime.NativeSupport.Module
NullReference
-Exceptions