TAA-Laufzeitconditions werden in den mit ExpEdge-Basisklassen unterstützten Implementierungen wie .NET Exceptions
behandelt. Wenn eine TAA-Laufzeitcondition auftritt und bis auf die Ebene der .NET Implementierung nicht behandelt wird, so wird hieraus dynamisch eine TAA .NET Condition
erzeugt. Die Klasse Condition
basiert auf der .NET-Klasse Exception
; somit kann die TAA-Laufzeitcondition wie eine .NET Exception
abgefangen werden.
try { // Verarbeitung catch (Condition cond) { // Fehlerbehandlung von TAA Laufzeitconditions } catch (Exception exc) { // Fehlerbehandlung aller übrigen Ausnahmen }
Man beachte, dass, wenn im vorgehenden Code der erste catch
fehlen würde, alle Ausnahmen (auch die TAA-Laufzeitconditions) im catch (Exception)
-Block abgehandelt werden würden. Somit kann beim catch
generell zwischen TAA Laufzeitconditions und sonstigen Ausnahmen differenziert werden.
Eine TAA-Laufzeitcondition basiert immer auf einer Meldung einer Meldungsgruppe. Die Meldung wird eindeutig durch den Gruppennamen und die Meldungsnummer innerhalb der Gruppe. Wenn bei der Generierung der Basis-Assembly auch Meldungsgruppen eingeschlossen werden, so werden für die Meldungen dieser Gruppe eigenständige, von Condition
abgeleitete Klassen generiert. Zur Laufzeit wird seitens der Infrastruktur geprüft, ob die aktuelle Implementierung über derart erzeugte Condition
-Klassen verfügt und sichergestellt, dass in dem Fall eine Condition
passend zur Meldung erzeugt wird.
try { // irgendwelche Aktionen } catch (BlRkwFehl.Message4 cond) { // Fehlerbehandlung für Vertrag mit einem obligatorischen Auflösungstermin }
Man beachte, dass durch die Generierung dieser Klassen bspw. Meldungsgruppen auch die Meldungstexte, gehörend zur Condition
, in IntelliSense® oder beim Hover über die Klasse als Tooltip gezeigt werden.
Außerdem basieren alle Meldungen einer Meldungsgruppe auf einer Klasse für diese Meldungsgruppe. Somit können auch Gruppen von TAA- Laufzeitconditions abgefangen werden:
try { // Verarbeitung } catch (BlTbfFehlCondition cond) { // Fehlerbehandlung für Fehler der Gruppe BL-TBF-FEHL }
Die Namen der generierten Klassen für die einzelnen Meldungen werden abgeleitet aus dem symbolischen Namen für die jeweilige Meldung.
ExpEdge stellt sicher, dass der symbolische Name im .NET-Kontext gültig ist. Wenn kein expliziter symbolischer Name angegeben wurde, ist der Name Message
, gefolgt durch die Meldungsnummer.
Es besteht in MessEdge auch die Möglichkeit, eine Meldungsgruppe einer Meldungsklasse zuzuordnen. In diesem Fall basieren die einzelnen Meldungen bzw. die Meldungsgruppe auf einer weiteren Klasse für die Meldungsklasse:
try { // Verarbeitung } catch (TaaimCondition cond) { // Fehlerbehandlung für TAA Infrastruktur Meldungen }
Der Abschnitt Condition
der Bausteinklasse erlaubt das Anlegen einer neuen Condition
. Dazu steht eine generische Methode New<>
zur Verfügung, mit der alle in der Basisassembly bekannten Conditions
erzeugt werden können, keine anderen.
throw Module.Condition.New<BlTbfFehl.Message10>(Condition.SeverityEnum.Info, Month);
Alternativ können die Conditions auch mit der Methode Create
über Meldungsgruppe und Meldungsnummer erzeugt werden. Das vorige Beispiel ist insofern semantisch identisch zum nachfolgenden Code:
throw Module.Condition.Create(Condition.SeverityEnum.Info, "BL-TBF-FEHL", 1, Month);
Man beachte, dass die zweite Variante nicht generisch ist, also keinen Typ der erzeugten Condition festlegt. Die gelieferte Condition wäre in diesem Beispiel allerdings trotzdem vom Typ BlTbfFehl.Message10
, sofern in dem aktuellen Prozess in irgendeiner Basis-Assembly dieser Typ generiert wurde. Wenn eine Condition angelegt wird, zu der in den generierten Basis-Assemblies keine Typdefinitionen vorliegen, ist die Condition vom Typ TeamWiSE.Runtime.Common.Condition
.
public ReadOnlyCollection<Condition> OwnConditions { get; } public ReadOnlyCollection<Condition> AllConditions { get; }
Mit diesen Methoden können alle oder nur die von dem aktuellen Baustein erzeugten Conditions
aufgelistet werden.
public SeverityEnum HighestSeverity { get; }
Liefert die höchste Severity
aller derzeit geführten Conditions.
public static void ShowAll();
Zeigt einen Dialog mit Informationen zu sämtlichen derzeit geführten Conditions.
Wenn in bestimmten Fehlersituationen mehr als eine Condition erzeugt und ggf. aufgeworfen muss, wird eine System.AggregateException
verwendet. Die Eigenschaft InnerExceptions
enthält dabei die Liste der Conditions. Um das Abfangen und Behandlen von Conditions in solche Fällen zu erleichtern, werden für alle generierten Meldungsklassen 2 sog. Extension Methoden erzeugt, welche in einem Exception Filter bzw. catch
-Handler verwendet werden können:
try { this.Data.Kunde._000Nnam = "hhhhj"; } catch (Exception x) when (x.HasZztaaom1Conditions()) { var cnds = x.Zztaaom1Conditions().ToList(); // wenn conditions hier behandelt werden können cnds.ForEach(c => c.Remove()); // else throw }
Die Methode bool HasMeldungConditions()
liefert true
, wenn die Exception
eine Condition von dem jeweiligen Typ ist, oder eine AggregateException
ist, die mindestens eine Condition von dem jeweiligen Typ enthält.
Die Methode IEnumerable<Meldung> MeldungConditions()
liefert eine Liste mit den Conditions vom den jeweiligen Typ, die in der Exception
oder AggregateException
enthalten sind.
Wenn eine Condition mit der Severity Warning
oder höher in dem aktuellen Baustein oder unterhalb des Bausteins geraised wird, so wird diese Condition in dem aktuellen Baustein aufgeworfen und kann mit catch
abgefangen werden.
Wenn für eine Condition ein Raise() ausgeführt wird, wird diese über die TAA-Infrastruktur behandelt; dabei kommen ggf. installierte Conditionhandler zum Zug.
Wenn für eine Condition ein throw() ausgeführt wird, wird diese behandelt wie eine Exception. Es erfolgt keine Behandlung durch die TAA-Infrastruktur; Conditionhandler wirken in dem Fall nicht.
Es kann jedoch1) auch eine abweichende Behandlung definiert werden. Dazu wird für bestimmte Klassen von Conditions oder für Conditions ab einer bestimmten Severity einen sogenannten Condition-Handler installiert:
public void RegisterHandler(Condition.SeverityEnum sev, Func<Condition, Condition.ActionEnum> func); public void RegisterHandler(String cls, Func<Condition, Condition.ActionEnum> func)
Der jeweils installierte Handler entscheidet dann auf Basis der konkreten Condition, wie diese behandelt werden soll. Der Handler bekommt die Condition als Argument und liefert eine Condition.ActionEnum
zurück, der über die nächsten Schritte entscheiden soll.
Condition.ActionEnum
kennt folgende Werte:
Eintrag | Bedeutung |
---|---|
ResumeNext | Die Behandlung der Condition ist abgeschlossen, die Verarbeitung kann mit der nächsten Anweisung fortgesetzt werden. |
ExitArbg | Der Workflow Zustand soll auf fehlerhaft gesetzt und der aktuelle Arbeitsgang beendet werden. |
ExitModl | Der aktuelle Baustein soll beendet werden und die Ausführung soll beim Aufrufer fortgesetzt werden. |
Beispiele:
ActionEnum HandleError(Condition cnd) { this.State.Active = StateEnum.Fehler; return ActionEnum.ExitModl; } this.Condition.RegisterHandler(SeverityEnum.Error, HandleError);
this.Condition.RegisterHandler(Condition.SeverityEnum.Error, cnd => cnd.Associations["MustAbort"] != null ? Condition.ActionEnum.ExitArbg : Condition.ActionEnum.ResumeNext);
Meistens wird jedoch - analog zu den EXEC TAA Anweisungen - auf Basis der Severity oder Klasse eine grundsätzliche Entscheidung getroffen. Dann sieht der ConditionHandler wie folgt aus:
this.Condition.RegisterHandler(Condition.SeverityEnum.Error, cnd => Condition.ActionEnum.ExitModl);
Um diese Art der Verwendung syntaktisch etwas zu verschönern, stellt die Klasse Condition neben der ActionEnum
-Definition die drei Handler ExitArbg
, ExitModl
und ResumeNext
bereit. In Kombination mit der using static
Anweisung auf dem Type TeamWiSE.Runtime.Common.Condition
sieht dann das Registrieren eines solchen Standard-Handlers wie folgt aus:
using static TeamWiSE.Runtime.Common.Condition; // ... this.Condition.RegisterHandler(SeverityEnum.Severe, ExitArbg);