<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>WWF</title>
        <link>http://blogs.ugidotnet.org/dsantarelli/category/WWF.aspx</link>
        <description>WWF</description>
        <language>it-IT</language>
        <copyright>Dario Santarelli</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>[WF] Cancellation Handling</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/15/wf-cancellation-handling.aspx</link>
            <description>&lt;p&gt;La cancellazione dell'esecuzione di un workflow è simile per certi versi al &lt;a href="http://msdn.microsoft.com/en-us/library/ms734771.aspx" target="_blank"&gt;Fault Handling&lt;/a&gt;: osando un parallelismo con il mondo della programmazione OO, potremmo affermare che se i Fault Handler possono essere paragonati ad un catch, i &lt;a href="http://www.microsoft.com/uk/msdn/screencasts/screencast/52/Windows-Workflow-Foundation-Cancellation-Handlers.aspx" target="_blank"&gt;Cancellation Handlers&lt;/a&gt; costituiscono il finally. Da un punto di vista pratico, l'utilità dei Cancellation Handlers si trova nella capacità di permettere l'esecuzione di operazioni (tipicamente notifiche, logging, cleanup delle risorse utilizzate...) prima che il workflow venga effettivamente terminato, senza alcuna possibilità di interruzione. Il processo di cancellazione infatti, una volta avviato, è inarrestabile.&lt;br /&gt;Un Cancellation Handler può essere definito sia a livello di Workflow (globale) che localmente a livello di Composite Activity (es. ParallelActivity, SequenceActivity). In quest'ultimo caso, il processo di cancellazione è attivato se almeno una delle attività figlie di una Composite Activity scatena un errore non gestito o è in esecuzione quando il workflow è cancellato (ad es. dall'applicazione host).&lt;br /&gt;Veniamo ora ad un aspetto interessante: &lt;strong&gt;un Cancellation Handler può non comportarsi esattamente come ci aspettiamo.&lt;/strong&gt; Ebbene si.&lt;br /&gt;Se ad esempio impostiamo un Cancellation Handler globale (a livello di workflow), non è detto che venga chiamato ogniqualvolta il Workflow subisce una cancellazione. Infatti, poiché la cancellazione può essere gestita anche localmente, in caso di errore saranno attivati solamente i Cancellation Handler delle Composite Activities che possiedono delle attività figlie in esecuzione. Per quanto riguarda il Cancellation Handler globale, invece, sarà attivato solo se la cancellazione viene invocata "esternamente" per l'intero workflow (tipicamente via UI/Applicazione Host).&lt;br /&gt;Vediamo un esempio: ecco un workflow che definisce una ParallelActivity con 3 branch, ciascuno dei quali munito di una propria sequenza interna. &lt;br /&gt;&lt;br /&gt;&lt;img src="http://img440.imageshack.us/img440/7211/cancellationhandlerssamcb4.jpg" /&gt;  &lt;/p&gt;&lt;p&gt;Supponendo che il branch centrale causi un' eccezione non gestita ( facendo passare inevitabilmente il workflow allo stato Terminated ), gli altri branch contenuti nella Parallel Activity principale verranno informati del fatto che il workflow sta per essere terminato, con conseguente attivazione dei relativi Cancellation Handlers. Stessa cosa vale anche per le Composite Activities ulteriormente nidificate. &lt;br /&gt;Tuttavia, i Cancellation Handlers della Composite Activity che ha generato l'eccezione, della Parallel Activity esterna e del Workflow, NON verranno svegliati, differentemente da quanto ci si potrebbe aspettare.&lt;br /&gt;&lt;br /&gt;Tirando le somme, è importante ricordare che il comportamento dei Cancellation Handler è strettamente dipendente dall'ordine di esecuzione delle attività al momento della cancellazione. Se da una parte possiamo pianificare la gestione dei Cancellation Handlers, dall'altra costituisce buona prassi (per ovvi motivi) NON implementare dipendenze logiche/funzionali tra i vari Cancellation Handlers e soprattutto sperimentare il loro comportamento nell'ambiente di esecuzione, in quanto può avere una natura variabile (addirittura eseguendo in modalità debug o meno).&lt;br /&gt;&lt;br /&gt;Technorati tags: &lt;a href="http://technorati.com/tag/Workflow"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=Workflow" /&gt;Workflow&lt;/a&gt; &lt;a href="http://technorati.com/tag/WF"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=WF" /&gt;WF&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/93036.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/15/wf-cancellation-handling.aspx</guid>
            <pubDate>Sun, 15 Jun 2008 15:37:55 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/15/wf-cancellation-handling.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/93036.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/93036.aspx</trackback:ping>
        </item>
        <item>
            <title>[WF] Creare un Custom Activity Layout</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/08/wf-creare-un-custom-activity-layout.aspx</link>
            <description>&lt;p&gt;Il designer di WF integrato in Visual Studio 2008 (o 2005 munito delle relative '&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=5D61409E-1FA3-48CF-8023-E8F38E709BA6&amp;amp;displaylang=en" target="_blank"&gt;extensions&lt;/a&gt;') utilizza le classi del namespace &lt;em&gt;System.Workflow.ComponentModel.Design&lt;/em&gt; per il controllo del rendering delle attività. In realtà il layout di una attività semplice (Activity) o composta (CompositeActivity) può essere personalizzato in maniera molto facile. &lt;br /&gt;Anzitutto, il designer sfrutta due classi base: &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.design.activitydesigner.aspx" target="_blank"&gt;ActivityDesigner&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.design.activitydesignertheme.aspx" target="_blank"&gt;ActivityDesignerTheme&lt;/a&gt;. La prima si occupa di gestire "come" un' attività verrà visualizzata nel designer (es. dimensioni, forma, editing etc.), mentre la seconda viene prettamente utilizzata per impostare il tema da associare al designer (es. colori, bordi etc.). Nello stesso namespace esistono inoltre diverse specializzazioni della classe base ActivityDesigner come &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.design.compositeactivitydesigner.aspx" target="_blank"&gt;CompositeActivityDesigner&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.design.sequentialactivitydesigner.aspx" target="_blank"&gt;SequentialActivityDesigner&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/it-it/library/system.workflow.componentmodel.design.parallelactivitydesigner.parallelactivitydesigner(VS.85).aspx" target="_blank"&gt;ParallelActivityDesigner&lt;/a&gt; etc.&lt;br /&gt;Quindi, estendendo opportunamente metodi e proprietà della classe base che scegliamo, possiamo apportare interessanti personalizzazioni.Vediamo un semplice esempio. &lt;br /&gt;Creiamo una classe MyCustomActivityDesignerTheme ereditata da ActivityDesignerTheme per definire il nostro tema.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.ComponentModel.Design;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;namespace&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; MyCustomActivityLibrary&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;internal&lt;/span&gt; &lt;span style="color: blue"&gt;sealed&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;MyCustomActivityDesignerTheme&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;ActivityDesignerTheme&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; MyCustomActivityDesignerTheme(&lt;span style="color: #2b91af"&gt;WorkflowTheme&lt;/span&gt; theme) : &lt;span style="color: blue"&gt;base&lt;/span&gt;(theme)&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;         &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.Initialize();&lt;br /&gt;         &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.BackColorStart = System.Drawing.&lt;span style="color: #2b91af"&gt;Color&lt;/span&gt;.Orange;&lt;br /&gt;         &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.BackColorEnd = System.Drawing.&lt;span style="color: #2b91af"&gt;Color&lt;/span&gt;.OrangeRed;&lt;br /&gt;         &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.BorderColor = System.Drawing.&lt;span style="color: #2b91af"&gt;Color&lt;/span&gt;.Red;&lt;br /&gt;         &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.BorderStyle = System.Drawing.Drawing2D.&lt;span style="color: #2b91af"&gt;DashStyle&lt;/span&gt;.Solid;&lt;span style="mso-spacerun: yes"&gt;            &lt;br /&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;/span&gt;&lt;span lang="EN-US" style="font-size: 9pt; color: #000066; font-family: 'Courier New'; mso-ansi-language: en-us"&gt;&lt;?xml:namespace prefix = o /?&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Quindi, ci concentriamo sul comportamento del rendering del designer implementando una classe MyCustomActivityDesigner derivata da ActivityDesigner, specificando che il tema da utilizzare sia quello sopra definito (MyCustomActivityDesignerTheme)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.ComponentModel.Design;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.ComponentModel;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Drawing;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;namespace&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; MyCustomActivityLibrary&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;[&lt;span style="color: #2b91af"&gt;ActivityDesignerTheme&lt;/span&gt;(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;MyCustomActivityDesignerTheme&lt;/span&gt;))]&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;internal&lt;/span&gt; &lt;span style="color: blue"&gt;sealed&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;MyCustomActivityDesigner&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;ActivityDesigner&lt;br /&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Initialize(&lt;span style="color: #2b91af"&gt;Activity&lt;/span&gt; activity)&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.Initialize(activity);&lt;span style="mso-spacerun: yes"&gt;      &lt;br /&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.Text = &lt;span style="color: #a31515"&gt;"[MyCustomActivity] "&lt;/span&gt; + activity.Name;&lt;span style="mso-spacerun: yes"&gt;                &lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Rectangle&lt;/span&gt; TextRectangle&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;get &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;span style="mso-spacerun: yes"&gt; ... &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Rectangle&lt;/span&gt; ImageRectangle&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;get &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{ &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;...&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="mso-spacerun: yes"&gt;    &lt;/span&gt;}&lt;br /&gt;   &lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;protected&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; OnPaint(&lt;span style="color: #2b91af"&gt;ActivityDesignerPaintEventArgs&lt;/span&gt; e)&lt;br /&gt;    &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{ ... &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Osserviamo come l'overriding di metodi e proprietà della classe ActivityDesigner (&lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.design.activitydesigner_members.aspx" target="_blank"&gt;qui&lt;/a&gt; la lista completa) ci permette di modificare particamente ogni aspetto del rendering. Nel nostro stupidissimo esempio è stata semplicemente estesta la logica del metodo &lt;em&gt;Initialize(...)&lt;/em&gt; per anteporre il prefisso "[MyCustomActivity]" al nome dell' attività di interesse. &lt;br /&gt;L'ultimo step è ovviamente l'associazione del designer realizzato nei confronti di una nostra attività custom (ShippingActivity) tramite l'impostazione dell' attributo Designer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.ComponentModel;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.ComponentModel.Design;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.Activities;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; System.Workflow.Activities.Rules;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;namespace&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; MyCustomActivityLibrary&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;[&lt;span style="color: #2b91af"&gt;Designer&lt;/span&gt;(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;MyCustomActivityDesigner&lt;/span&gt;))]&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ShippingActivity&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;Activity&lt;br /&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{ ... }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Il risultiamo che otteniamo è il seguente:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://img386.imageshack.us/img386/8435/customactivityxh9.jpg" /&gt; &lt;br /&gt;&lt;br /&gt;Technorati tags: &lt;a href="http://technorati.com/tag/Workflow%20Foundation"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=Workflow%20Foundation" /&gt;Workflow Foundation&lt;/a&gt; &lt;a href="http://technorati.com/tag/WF"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=WF" /&gt;WF&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/92968.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/08/wf-creare-un-custom-activity-layout.aspx</guid>
            <pubDate>Sun, 08 Jun 2008 16:18:47 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/06/08/wf-creare-un-custom-activity-layout.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/92968.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/92968.aspx</trackback:ping>
        </item>
        <item>
            <title>[Windows Workflow Foundation] Utilizzo della WhileActivity.DynamicActivity</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/22/windows-workflow-foundation-utilizzo-della-whileactivity.dynamicactivity.aspx</link>
            <description>&lt;p&gt;La &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.activities.whileactivity.aspx" target="_blank"&gt;WhileActivity&lt;/a&gt; è una attività di uso abbastanza comune in WWF, ma il suo utilizzo implica spesso di tenere in considerazione un paio questioni non così banali:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Può contenere una sola attività figlio. Quindi, per eseguire attività multiple al suo interno occorre utilizzare un' attività "wrapper" (come la &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.compositeactivity.aspx" target="_blank"&gt;CompositeActivity&lt;/a&gt; o la &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.activities.sequenceactivity.aspx" target="_blank"&gt;SequenceActivity&lt;/a&gt;) che contenga l'insieme le nostre attività da eseguire.  &lt;/li&gt;&lt;li&gt;Ad ogni iterazione il runtime crea una nuova istanza dell'attività figlia della WhileActivity e di conseguenza ciascuna attività possiederà un contesto di esecuzione indipendente.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Partendo da queste due assunzioni, nel caso in cui volessimo accedere programmaticamente ad un' attività figlia (base o custom) all'interno della nostra WhileActivity, abbiamo bisogno di ricorrere alla proprietà &lt;a href="http://msdn.microsoft.com/it-it/library/system.workflow.activities.whileactivity.dynamicactivity.aspx" target="_blank"&gt;WhileActivity.DynamicActivity&lt;/a&gt; per reperirne la reference d'istanza.&lt;br /&gt;Ad esempio, supponendo di voler accedere ad una nostra attività custom &lt;em&gt;ShippingActivity&lt;/em&gt; inserita all'interno di una SequenceActivity iterata da una WhileActivity, possiamo utilizzare del codice come il seguente:&lt;br /&gt;&lt;br /&gt;&lt;span lang="EN-US" style="font-size: 8pt; color: blue; line-height: 115%; font-family: 'Courier New'; mso-ansi-language: en-us; mso-fareast-font-family: 'Times New Roman'; mso-fareast-theme-font: minor-fareast; mso-fareast-language: it; mso-bidi-language: ar-sa"&gt;using &lt;/span&gt;&lt;span lang="EN-US" style="font-size: 8pt; line-height: 115%; font-family: 'Courier New'; mso-ansi-language: en-us; mso-fareast-font-family: 'Times New Roman'; mso-fareast-theme-font: minor-fareast; mso-fareast-language: it; mso-bidi-language: ar-sa"&gt;CustomActivityLibrary;&lt;/span&gt; &lt;span style="font-size: 8pt; color: green; font-family: 'Courier New'"&gt;// Libreria di attività custom&lt;/span&gt;&lt;br /&gt;...&lt;br /&gt;&lt;span style="font-size: 8pt; color: green; font-family: 'Courier New'"&gt;// La DynamicActivity in questo caso è una SequenceActivity 'wrapper' che contiene più attività&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 8pt; color: #2b91af; font-family: 'Courier New'"&gt;ShippingActivity&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; shippingActivity = (&lt;span style="color: #2b91af"&gt;ShippingActivity&lt;/span&gt;)myWhileActivity.DynamicActivity.GetActivityByName(&lt;span style="color: #a31515"&gt;"shippingActivity"&lt;/span&gt;, &lt;span style="color: blue"&gt;true&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; color: green; font-family: 'Courier New'"&gt;// Do something...&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;In particolare, il metodo &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.activity.getactivitybyname.aspx" target="_blank"&gt;GetActivityByName&lt;/a&gt; con il secondo parametro impostato a &lt;em&gt;true&lt;/em&gt; ritorna l'istanza della ShippingActivity assumendo che essa sia figlia della SequenceActivity (in questo caso la DynamicActivity) oggetto dell'iterazione tramite la WhileActivity. &lt;br /&gt;&lt;br /&gt;Technorati tags: &lt;a href="http://technorati.com/tag/Workflow"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=Workflow" /&gt;Workflow&lt;/a&gt; &lt;a href="http://technorati.com/tag/WWF"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=WWF" /&gt;WWF&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/92772.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/22/windows-workflow-foundation-utilizzo-della-whileactivity.dynamicactivity.aspx</guid>
            <pubDate>Thu, 22 May 2008 19:56:52 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/22/windows-workflow-foundation-utilizzo-della-whileactivity.dynamicactivity.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/92772.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/92772.aspx</trackback:ping>
        </item>
        <item>
            <title>[Windows Workflow Foundation] Modificare un Workflow a run-time</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/15/windows-workflow-foundation-modificare-un-workflow-a-run-time.aspx</link>
            <description>&lt;p&gt;Un' interessante possibilità che ci viene offerta da Workflow Foundation riguarda il cambiamento dinamico a run-time dell'albero delle attività di un' istanza di un workflow. In realtà, escludendo scenari particolari che richiedono una certa flessibilità nella composizione di un workflow, non ritengo che questa costituisca una prassi così consigliabile, considerando ad esempio i ritardi di esecuzione oppure i possibili ulteriori problemi che potrebbero affliggere il runtime a seguito di modifiche dinamiche in fase di esecuzione. &lt;br /&gt;Ad ogni modo, WWF ci permette di aggiornare dinamicamente un'istanza di workflow in termini di aggiunta/rimozione attività (anche custom), cambiamento del flow control, aggiornamento della logica condizionale (If-Else) , ma soprattutto in termini di gestione di nuovi eventi.&lt;br /&gt;All'atto pratico ci sono due modi per apportare modifiche ad un' istanza di un workflow in esecuzione: &lt;u&gt;all'interno della logica del workflow stesso, oppure all'interno della logica dell'applicazione host&lt;/u&gt;. E' evidente che dal punto di vista del runtime, le modifiche interesseranno solo ed esclusivamente una precisa istanza di un workflow, dal momento che altre istanze potrebbero essere in esecuzione e non interessate al cambiamento previsto. Ciò significa che quando la nostra istanza di workflow raggiungerà lo stato &lt;em&gt;Completed&lt;/em&gt;, i nostri cambiamenti 'moriranno' con essa poiché non coinvolgono la definizione originale del workflow.&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;Cambiamenti all'interno dell'istanza di workflow&lt;/strong&gt;&lt;br /&gt;Prima domanda: "Dove inseriamo il nostro codice che modifica il comportamento del workflow?" Risposta: tipicamente all'interno di un event handler di una attività (anche custom) del workflow stesso, ma preferibilmente ovunque il workflow si trovi in uno stato &lt;em&gt;Suspended&lt;/em&gt; o &lt;em&gt;Idled&lt;/em&gt; (ricordiamoci che stiamo lavorando su un' istanza in esecuzione). &lt;br /&gt;Vediamo un semplice esempio: abbiamo un &lt;em&gt;SampleWorkflow&lt;/em&gt; (che deriva dal solito &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.activities.sequentialworkflowactivity.aspx" target="_blank"&gt;SequentialWorkflowActivity&lt;/a&gt; - ovvero una rappresentazione di un workflow che esegue delle attività sequenzialmente) in cui vogliamo aggiungere un' attività custom &lt;em&gt;SumActivity&lt;/em&gt; che dietro le quinte non fa altro che sommare due interi A e B esposti come proprietà. &lt;br /&gt;Possiamo inserire questo 'cambiamento' all'interno della logica di una &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.activities.codeactivity.aspx" target="_blank"&gt;CodeActivity&lt;/a&gt; già definita a livello di workflow:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;public&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;SampleWorkflow&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;SequentialWorkflowActivity&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; line-height: 115%; font-family: 'Courier New'; mso-ansi-language: it; mso-fareast-font-family: 'Times New Roman'; mso-fareast-theme-font: minor-fareast; mso-fareast-language: it; mso-bidi-language: ar-sa"&gt;{&lt;/span&gt; &lt;br /&gt;  &lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;private&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; codeActivity_ExecuteCode(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)&lt;br /&gt; &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;   ...&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;CustomActivityLibrary.&lt;span style="color: #2b91af"&gt;SumActivity&lt;/span&gt; sumActivity = &lt;span style="color: blue"&gt;new&lt;/span&gt; CustomActivityLibrary.&lt;span style="color: #2b91af"&gt;SumActivity&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: #2b91af"&gt;   WorkflowChanges&lt;/span&gt; changes = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WorkflowChanges&lt;/span&gt;(&lt;span style="color: blue"&gt;this&lt;/span&gt;);&lt;span style="mso-spacerun: yes"&gt;       &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;   sumActivity.A = 2;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;   sumActivity.B = 4;&lt;span style="mso-spacerun: yes"&gt;          &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;   changes.TransientWorkflow.Activities.Add(sumActivity);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;   changes.Validate();&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: blue"&gt;   this&lt;/span&gt;.ApplyWorkflowChanges(changes);&lt;br /&gt;&lt;br /&gt;   ...&lt;br /&gt;  }&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Osserviamo immediatamente l'utilizzo della classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.workflowchanges(VS.85).aspx" target="_blank"&gt;WorkflowChanges&lt;/a&gt;, che espone la proprietà &lt;a href="http://msdn2.microsoft.com/en-us/library/system.workflow.componentmodel.workflowchanges.transientworkflow.aspx" target="_blank"&gt;TransientWorkflow&lt;/a&gt;, ovvero una &lt;u&gt;clonazione dell'albero delle attività dell'istanza del workflow corrente&lt;/u&gt; a cui applicare i cambiamenti, che in seguito verranno propagati alla corretta istanza del workflow (lasciando le altre istanze immutate). Il metodo &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.componentmodel.workflowchanges.validate(VS.85).aspx" target="_blank"&gt;Validate&lt;/a&gt; si occupa di controllare preventivamente la semantica dei cambiamenti e quindi che non si verifichino potenziali eccezioni. Infine, tramite il metodo &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.workflowinstance.applyworkflowchanges(VS.85).aspx" target="_blank"&gt;ApplyWorkflowChanges&lt;/a&gt; applichiamo i cambiamenti implementati direttamente sull'istanza del workflow in esecuzione.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cambiamenti all'interno dell'applicazione Host&lt;br /&gt;&lt;/strong&gt;Diversamente dal caso precedente, i cambiamenti su un' istanza di un workflow vengono effettuati a partire dall'applicazione host, sfruttando le API messe a disposizione da WWF. Osservando il seguente esempio, si nota subito come l'unica differenza si trovi nel modo con cui andiamo a reperire l'istanza sui cui andare ad apportare le nostre personalizzazioni: in questo caso infatti un'istanza di workflow viene creata tramite il metodo &lt;a href="http://msdn.microsoft.com/en-us/library/ms594868(VS.85).aspx" target="_blank"&gt;CreateWorkflow&lt;/a&gt; del runtime e tramite il metodo &lt;em&gt;GetWorkflowDefinition()&lt;/em&gt; non facciamo altro che puntare alla relativa attività root. Il codice dunque non fa altro che 'appendere' semplicemente la nostra SumActivity all'albero delle attività così come definito in &lt;em&gt;SampleWorkflow&lt;/em&gt;.&lt;/p&gt; &lt;p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none"&gt;&lt;span style="font-size: 8pt; color: blue; font-family: 'Courier New'"&gt;using&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; (&lt;span style="color: #2b91af"&gt;WorkflowRuntime&lt;/span&gt; workflowRuntime = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WorkflowRuntime&lt;/span&gt;())&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;{&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-size: 8pt; color: #2b91af; font-family: 'Courier New'"&gt;WorkflowInstance&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt; workflow_instance = workflowRuntime.CreateWorkflow(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;SampleWorkflow&lt;/span&gt;));&lt;span style="mso-spacerun: yes"&gt;                &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: #2b91af"&gt;  WorkflowChanges&lt;/span&gt; changes = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WorkflowChanges&lt;/span&gt;(workflow_instance.GetWorkflowDefinition());&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  CustomActivityLibrary.&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;&lt;span style="color: #2b91af"&gt;SumActivity&lt;/span&gt; sumActivity = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;CustomActivityLibrary.&lt;/span&gt;&lt;span style="color: #2b91af"&gt;SumActivity&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  sumActivity.A = 2;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  sumActivity.B = 4;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  changes.TransientWorkflow.Activities.Add(sumActivity);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  changes.Validate();&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 8pt; font-family: 'Courier New'"&gt;  workflow_instance.ApplyWorkflowChanges(changes);&lt;br /&gt;&lt;br /&gt;  ...&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;br /&gt;Technorati tags: &lt;a href="http://technorati.com/tag/Workflow"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=Workflow" /&gt;Workflow&lt;/a&gt; &lt;a href="http://technorati.com/tag/WWF"&gt;&lt;img alt=" " src="http://static.technorati.com/static/img/pub/icon-utag-16x13.png?tag=WWF" /&gt;WWF&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/92672.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/15/windows-workflow-foundation-modificare-un-workflow-a-run-time.aspx</guid>
            <pubDate>Thu, 15 May 2008 00:30:26 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/05/15/windows-workflow-foundation-modificare-un-workflow-a-run-time.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/92672.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/92672.aspx</trackback:ping>
        </item>
    </channel>
</rss>