in

DotNetSide

Dot Net South Italy Developers User Group

Articoli

Articoli pubblicati dagli iscritti a .netSide

Introduzione a Windows Workflow Foundation 4

di Raffaele Fanizzi

Questo è il primo di una serie di articoli che hanno l’obiettivo di presentare l’API Windows Workflow Foundation integrata nel .NET Framework 4.

Un workflow non è altro che un modo per descrivere una serie di attività, il loro ordine di esecuzione, le relazioni che ci sono tra loro, atte a modellare un lavoro da eseguire sia nel breve, che nel lungo periodo.

Facciamo un esempio pratico. Supponiamo di dover realizzare un’applicazione per una videoteca, il cui scopo è quello di tener traccia di tutti i film che possiede e, per ogni film, del loro stato. Gli stati possibili sono i seguenti: in sede, noleggiato e in ritardo. Senza addentrarci troppo nel merito di questo dominio applicativo, per realizzare quest’applicazione e, in particolare, per tener traccia dello stato di un film è possibile seguire due strade. La prima è quella di gestire manualmente sia la logica applicativa attraverso il codice, che la persistenza dello stato di ogni film. La seconda è di affidarsi ad un’infrastruttura come quella che mette a disposizione Windows Workflow Foundation, per modellare il flusso degli stati di un film in maniera sia dichiarativa, che programmatica.

Chi segue il mondo della programmazione .NET sa bene che Windows Workflow Foundation non è un’esclusiva del .NET Framework 4, ma una precedente versione era già stata rilasciata sotto lo stesso nome con il .NET Framework 3.0.

In realtà, invece di parlare di versioni diverse, sarebbe proprio il caso di considerarle API completamente diverse perché la versione più recente, che per chiarezza chiamerò d’ora in avanti Windows Workflow Foundation 4 o WF4, non ha nulla a che fare con quella precedente (Windows Workflow Foundation 3 o WF3).

Microsoft ha, infatti, deciso di reingegnerizzare completamente quest’API anche perché, se dobbiamo dirla tutta, posso affermare con ragionevole certezza che WF3 è stata libreria, tra quelle introdotte con il .NET Framework 3.0, che ha riscosso meno successo.

La reingegnerizzazione ha riguardato il runtime, il modello di programmazione e il tool per la definizione grafica del workflow (designer). L’obiettivo di questo lavoro è stato quello di incrementare le prestazioni e di facilitare il più possibile il programmatore nell’adozione di WF4 per gestire la logica delle proprie applicazioni.

E’ importante chiarire che WF3 non è stato abbandonato a se stesso, ma continua ad essere supportato nel .NET Framework 4, benché sia ben separato dal WF4. Gli assembly legati al WF3 sono System.Workflow.*, mentre il nuovo WF4 lo troviamo negli assembly System.Activities.*.

La classe attorno alla quale ruota tutta la definizione di un workflow in WF4 è Activity. Questa classe rappresenta un’attività, termine con il quale si intende non solo la singola attività semplice ed atomica, ma anche un raggruppamento di più attività di diverso tipo tra loro. Attraverso questa definizione gerarchica si arriva facilmente a desumere che di fatto un workflow in WF4 non è altro che un’Activity che ne integra altre.

Andiamo quindi a realizzare il nostro primo workflow. Come detto in precedenza, con WF4 è possibile definire un workflow sia in maniera dichiarativa, che programmatica. Di seguito trovate un esempio di uno stesso workflow dichiarato sia da codice, sia sfruttando il designer integrato in Visual Studio 2010.

 

clip_image001

 

Il codice non fa altro che dichiarare un’istanza di tipo Sequence, che è un tipo di attività che, come tutte le attività, deriva dalla classe base Activity. Sequence ha una proprietà chiamata Activities che è una collezione di Activity. All’interno di questa collezione ho dichiarato due attività di tipo WriteLine che è un altro tipo di attività che deriva dalla classe base Activity.

Tutti i tipi di attività che ho usato sono integrati all’interno di WF4 e, senza entrare troppo nel merito del comportamento di tutte le attività che mette a disposizione il framework (aspetto che vedremo in un successivo articolo),  per il momento è sufficiente sapere che la Sequence non è altro che un’attività contenitore di altre attività eseguite in sequenza, mentre WriteLine scrive testo in un TextWriter, utilizzando di default il TextWriter della console.

L’equivalente workflow definito attraverso il designer è il seguente.

 

clip_image003

 

Quando definite il workflow utilizzando il designer vi invito a fare attenzione ad un particolare: la proprietà Text dell’attività WriteLine non è una semplice stringa, ma richiede in input un’espressione Visual Basic ed è questo il motivo per cui la stringa va impostata completa di virgolette, come se si stesse scrivendo codice VB.NET. Il perché di questa scelta sarà più chiaro tra qualche paragrafo.

Il codice completo del main per inizializzare ed avviare i due workflow che abbiamo definito è il seguente.

 

clip_image004

 

La classe utilizzata per avviare l’esecuzione dei workflow è WorkflowInvoker. Poiché ho intenzione di dedicare un articolo esclusivamente all’hosting di un workflow in WF4, è prematuro a questo livello entrare nei dettagli. Per il momento considerate il WorkflowInvoker come una semplice classe per l’esecuzione sincrona e asincrona di istanze di un workflow. Nell’esempio è stato usato il metodo statico Invoke che esegue in modo sincrono il workflow in input.

Concludiamo questo primo articolo dedicato a WF4 con la spiegazione di come viene gestito il flusso di dati all’interno di un workflow.

Un’attività può lavorare su dati in input, restituire dati in output, immagazzinare dati al suo interno e processarli. Questi fondamentali compiti sono gestiti da WF4 con gli argomenti, le variabili e le espressioni.

Come già detto, tutte le attività di un workflow estendono la classe base Activity al punto che lo stesso workflow non è altro che un Activity con, eventualmente, delle sotto Activity. Queste attività possono richiedere dei parametri in input e restituirne altri in output.

Un esempio è rappresentato dall’attività WriteLine utilizzata nel precedente esempio. Questa ha una proprietà denominata Text che è di tipo InArgument<string>, cioè è un argomento in input di tipo stringa.

L’aspetto curioso della classe InArgument<T> è che estende la classe Argument che a sua volta possiede una proprietà denominata Expression di tipo Activity<T>, cioè un’attività che restituisce in output un risultato di tipo T, dove T nel caso della WriteLine è il tipo stringa. Questo giro potrebbe risultare essere complesso, ma è un’ulteriore prova di come praticamente qualsiasi cosa all’interno dei workflow di WF4 derivi dalla classe Activity.

Tornando alla nostra attività WriteLine, possiamo fare in modo di passargli in input un argomento di tipo stringa chiamato “Text”, invece di definirglielo attraverso una costante. Il seguente codice assolve a questo compito.

 

clip_image005

 

In questo esempio il workflow è rappresentato dalla sola attività WriteLine e, sfruttando un overload del metodo Invoke della classe WorkflowInvoker, passiamo in input al nostro workflow il parametro “Text” attraverso un Dictionary<string,object>. Prestate attenzione quando passate in input ad un Activity un argomento utilizzando un dizionario: i nomi dei parametri sono case sensitive.

In questo esempio abbiamo utilizzato l’attività WriteLine per comodità, perché ha già integrata all’interno della sua definizione un parametro in input. Naturalmente possiamo definire noi stessi un workflow con i suoi parametri in input ed è esattamente quello che mi accingo a fare riprendendo il workflow costruito con il designer in precedenza.

 

clip_image007

 

Nella finestra del designer, in basso, troverete il pulsante “Arguments”. Selezionandolo si aprirà una griglia che riporta l’elenco degli argomenti definiti per il vostro workflow. Definiamone due in input di tipo stringa chiamati “Text1” e “Text2”. Eventualmente potete anche definire un valore di default.

A questo punto, spostatevi nelle textbox relative alla proprietà Text delle attività WriteLine e potrete scrivere all’interno il nome degli argomenti appena definiti, con tanto di supporto da parte dell’Intellisense. Questo non deve sorprendere più di tanto perché la proprietà Text, come detto in precedenza, è un InArgument<string> che integra al suo interno un’espressione Visual Basic e, di conseguenza, è possibile scrivere al suo interno codice VB.NET a patto che, una volta valutato, riporti come valore di ritorno una stringa. Nel nostro caso non abbiamo fatto altro che assegnargli il valore dei due argomenti passati in input al workflow.

Di seguito il codice per richiamare il workflow appena definito con i due parametri in input.

 

clip_image008

 

Analogamente ai parametri in input è possibile definire anche parametri in output dal workflow. La procedura da seguire è la stessa appena vista, con la differenza che è necessario assegnare il parametro in output ad un valore all’interno del workflow. Per raggiungere quest’obiettivo abbiamo utilizzato una nuova attività chiamata Assign che consente di eseguire assegnazioni.

 

clip_image010

 

L’attività Assign è stata utilizzata in questo caso per assegnare al parametro in output un’espressione VB.NET che esegue la concatenazione tra i due parametri in input.

Il codice per richiamare questo nuovo workflow e leggere il suo parametro in output è il seguente.

 

clip_image011

 

Il metodo Invoke della classe WorkflowInvoker restituisce come valore di ritorno un IDictionary<string, object> attraverso il quale è possibile accedere ai parametri in output.

Completiamo questa panoramica discutendo delle variabili. Esattamente come avviene nella programmazione di tutti i giorni, anche nel caso dei workflow le variabili hanno il compito di immagazzinare un’informazione sulla base della quale può basarsi la logica applicativa.

Per definire una variabile è sufficiente selezionare la voce “Variables” in basso al designer di un workflow e definirle in maniera analoga a quanto è stato fatto per gli argomenti in input/output. A differenza dei parametri di input/output, tuttavia, le variabili non hanno una direzione e, invece, hanno uno scope, cioè una regione all’interno della quale sono definite. Poiché un workflow non è altro che un’attività che può contenere gerarchicamente altre attività, quando si definisce una variabile è necessario chiarire quale è il suo raggio d’azione.

Di seguito un esempio di workflow che fa uso di una variabile.

 

clip_image013

 

In questo esempio il workflow integra una variabile denominata “variabileIntera” di tipo intero, che ha uno scope pari a tutta la Sequence. A seguito delle due attività WriteLine, mediante l’attività Assign, assegno questa variabile ad un’espressione VB.NET che, essenzialmente, genera un numero intero casuale da 0 a 100 utilizzando come seed i secondi del DateTime.Now in modo da dare un po’ di variabilità al suo comportamento.

A seguito di questa assegnazione utilizzo l’attività If per valutare un’espressione VB.NET che, in questo caso, verifica se il valore della variabile è maggiore di 50. Dipendentemente da questa valutazione, l’attività sarà eseguita all’interno del ramo Then o Else, cioè assegnerò al mio parametro in output la stringa Text1 o Text2.

Come avrete certamente notato, la totalità delle operazioni effettuate è molto semplice. L’utilizzo delle espressioni Visual Basic è al contempo banale e potente e anche il nuovo designer integrato in Visual Studio 2010 è estremamente intuitivo.

Bene, con questo primo articolo penso di aver stuzzicato abbastanza la vostra curiosità in merito a WF4. Nel prossimo approfondiremo meglio le varie attività integrate nel framework, oltre ad illustrare la creazione di attività custom.

Comments

 

Twitter Trackbacks for Introduzione a Windows Workflow Foundation 4 - Articoli [dotnetside.org] on Topsy.com said:

Pingback from  Twitter Trackbacks for                 Introduzione a Windows Workflow Foundation 4 - Articoli         [dotnetside.org]        on Topsy.com

June 14, 2010 3:33 AM
 

Articoli said:

di Raffaele Fanizzi Nel precedente articolo ho effettuato un’introduzione a Windows Workflow Foundation

November 8, 2010 1:33 AM
 

rimonabantexcellence site title said:

Pingback from  rimonabantexcellence site title

June 7, 2013 11:55 AM
 

propecia said:

Pingback from  propecia

June 13, 2013 6:21 AM
Powered by Community Server (Commercial Edition), by Telligent Systems