Es gibt nichts schlimmeres wie eine Anwendung oder ein Framework das nicht flexibel genug für Erweiterungen ist. Zum Glück ist es nicht so bei der Workflow Foundation 4. Denn das Framework bietet einige elegante Wege seine gewünschte Logik dazwischen zu klinken. Eines davon ist das Workflow Extension Feature. Hierbei kann eine Instanz mittels Referenzierung an Activities geleitet werden. In den meisten Fällen dient dieses Feature vor allem um den Workflow Hoster mit Events zu erweitern, die dann vom Workflow auf der Code-Ebene auslösen lässt. Das hört sich sehr kompliziert an. Keine Panik! Das folgende Beispiel zeigt „wie“ und „wann“ so etwas umgesetzt wird.
Beispiel: WorkflowExtensionExample
Dazu wird Visual Studio 2010 geöffnet und ein neues Projekt angelegt. Als Template wird unter “Workflow” – “Workflow Console Application” gewählt. Als Name wird “WorkflowExtensionExample” verwendet.
Abb. 1 - Neues “Workflow Console Application” Projekt erzeugen.
Workflow deklarieren
Folgende Schritte sollen nun dem Workflow definiert werden:
-
- Dem Workflow ein Flowchart Activity setzen.
- Dem Flowchart Activity eine Variable Counter mit dem Typ int und einem Default-Wert von 0 setzen.
- Dem Flowchart Activity ein Assign Activity hinzufügen. Das Assign Activity soll die Variable Counter jeweils um einen Wert erhöhen (siehe Abb.2).
- Dem Flowchart Activity ein Delay Activity hinzufügen und dem Property Duration folgenden Wert setzen:
TimeSpan.FromSeconds(1)
- Gegen Ende alle miteinander von oben nach unten Verknüpfen.
Ist alles korrekt umgesetzt worden sollte es im Designer aussehen wie unter Abb.2 veranschaulicht wird.
Abb. 2 – Counter Workflow
Wie beim Blog-Eintrag “Einstieg zur Workflow Foundation 4 : Activity selbst schreiben” gezeigt wurde, werden Daten immer gegen Ende eines laufenden Workflows mittels Dictionary geliefert. Nun besteht allerdings folgendes Szenario: Der Workflow Hoster wird innerhalb der Console gehalten und startet einen endlos laufenden Workflow.
Wie sollte man also auf die Daten vom Workflow kommen? Ganz einfach! Es wird eine Klasse mit Event und einer Methode benötigt. Das Event wird dann von der Code-Ebene abonniert. Von einem selbstgeschriebenen Activity wird dann die Methode aufgerufen die dann das Event mit Daten auslöst. Die Instanz zu dieser Klasse wird dann von der Workflow Runtime geliefert.
Für eine solche Klasse würde der Contract (Interface) wie unter Listing 1 aussehen.
1: public interface IWFEventExtension
2: {
3: event Action<string> SomeDataFromWF;
4: void SetData(string value);
5: }
Listing 1 – Contract für die spätere Extension-Klasse.
Dann wird eine Klasse mit dem Namen WFEventExtension angelegt, die anschließend den Contract IWFEventExtension zugewiesen bekommt. Die Methode SetData bekommt dann die Implementierung um das Event zu feuern (siehe Listing 2).
1: public class WFEventExtension : IWFEventExtension
2: {
3: public event Action<string> SomeDataFromWF;
4:
5: public void SetData(string value)
6: {
7: if (SomeDataFromWF != null)
8: SomeDataFromWF(value);
9: }
10: }
Listing 2 – Die WFEventExtension-Klasse.
In der Program.cs-Datei wird von der WFEventExtension-Klasse eine Instanz erzeugt. Dann wird das SomeDataFromWF-Event abonniert. Wenn das Event ausgelöst wird, soll in dessen Methode die Parameter auf den Bildschirm mittels Console.WriteLine ausgeben. Dann folgt eine Instanz vom WorkflowInvoker. Durch die Methode Extensions.Add kann der Workflow Runtime dann die Instanz vom WFEventExtension überreicht werden. Der Code dazu steht unter Listing 3.
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: WFEventExtension wfEventExtension = new WFEventExtension();
6: wfEventExtension.SomeDataFromWF += wfEventExtension_SomeDataFromWF;
7:
8: WorkflowInvoker workflowInvoker = new WorkflowInvoker(new Workflow1());
9: workflowInvoker.Extensions.Add(wfEventExtension);
10: workflowInvoker.Invoke();
11:
12: Console.ReadLine();
13: }
14:
15: static void wfEventExtension_SomeDataFromWF(string value)
16: {
17: Console.WriteLine(value);
18: }
19: }
Listing 3 – Workflow Hoster mit Workflow Extension.
Jetzt wird nur noch ein selbst geschriebenes Activity benötigt, das sich die Instanz von der Workflow Runtime geben lässt.
Dazu wird eine neue Klasse mit dem Namen SetDataToSourceCode angelegt. Als Basisklasse wird die CodeActivity-Klasse verwendet. Der Wert aus dem Workflow soll anschließend über ein InArgument-Property vom Typ String folgen. Um nun auf die Extension-Instanz zu kommen wird auf die Workflow Runtime über den Parameter context.GetExtension zugegriffen. Anschließend wird die Methode SetData mit den Daten aufgerufen. Die Methode feuert später automatisch das Event auf Code-Ebene.
Der Code dazu ist unter Listing 4.
1: using System.Activities;
2:
3: namespace WorkflowExtensionExample
4: {
5: public class SetDataToSouceCode : CodeActivity
6: {
7: public InArgument<string> ValueFromVariable { get; set; }
8:
9: protected override void Execute(CodeActivityContext context)
10: {
11: IWFEventExtension wfEventExtension = context.GetExtension<IWFEventExtension>();
12: wfEventExtension.SetData(ValueFromVariable.Get(context));
13: }
14: }
15: }
Listing 4 – Eigenes SetDataToSourceCode-Activity das auf die Extension zugreift.
Das selbstgeschriebene Activity kann nun dem Workflow hinzugefügt werden. Dazu muss das Projekt komplett gebuildet werden [Strg] + [Shift] + [B]. Dann wird das Activity auch schon in der Toolbox zur Verfügung gestellt. Dieses wird beim 1. Schritt ganz einfach mittels Drag & Drop unter dem Delay Activity hinzugefügt. Beim 2. Schritt werden dann nur noch die Kommunikationsrichtungen zugewiesen. Ganz wichtig ist hierbei das nach der Verarbeitung vom SetDataToSourceCode Activity das Assign Activity wieder aufgerufen wird, um eine Schleife zu bilden (siehe Abb.3).
Abb. 3 – Das SetDataToSourceCode Activity wird hinzugefügt.
Jetzt kann wie gewohnt die Anwendung mittels [F5]-Tastendruck ausgeführt werden.
Abb. 4 – Ausgabe des Counters.
Das Beispiel sollte nun vermittelt haben “wie” eine Workflow Extension erzeugt und bereitgestellt wird. Unter Abb.5 wird das komplette Szenario nochmals grafisch abgebildet.
Abb. 5 – Das Beispiel im Detail
- Eine Instanz der WFEventExtension wird erzeugt und das SomeDataFromWF-Event wird abonniert. Die WFEventExtension Instanz wird der Workflow Runtime mittels Extensions.Add-Methode vom WF Hoster hinzugefügt.
- Der Workflow läuft und ruft das SetDataToSourceCode Activity auf.
- Das SetDataToSourceCode Activity holt sich von der Workflow Runtime die WFEventExtension Instanz und ruft die SetData-Methode auf. Die SetData-Methode löst auf Code-Ebene das Event aus, worin die Daten vom Workflow enthalten sind.
Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitten "kicken" sie ihn.
