Inhaltsverzeichnis

Basisimplementierung

Allgemein

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.

Definition der Implementierungsklasse

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
	{

 Implementierungsangaben

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.

Implementierungscode

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 RunImplementation2) ü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:

runimpl.cs
protected override void RunImplementation()
{
	InitializeGeneralConnections();
	try {
		switch (Operation.Active) {
		case OperationEnum.Durchfuehren:
			InitializeSpecialConnections();
			OperationDurchfuehren();
			break;
		default:
			OperationUdef();
			break;
		}
	}
	finally {
		Cleanup();
	}
}

Basisklasse

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:

Eigenschaften

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.

Methoden

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.

Dispose

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.

1)
früher Events
2)
Wie man sieht, wird nicht die Methode 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.
3)
also auf der Klasse TeamWiSE.Runtime.NativeSupport.Module
4)
nur innerhalb des gleichen Prozesses und des gleichen Gevos
5)
bspw. NullReference-Exceptions