Monday, July 14, 2008

Esecuzione di un workflow usando XOML

. Monday, July 14, 2008

E' possibile eseguire un workflow passando al metodo CreateWorkflow un tipo di flusso:

   1: WorkflowInstance instance = runtime.CreateWorkflow(typeof(Workflow1));
oppure facendo uso di tag basati su XAML.
Prima di spiegare il come, faccio un piccolo passo indietro per dire che Workflow Foundation ci permette di creare un flusso di lavoro essenzialmente in tre modi:
-solo codice, ne scaturisce che deve essere necessariamente compilato;
-separazione del codice, quindi code-behind più markup del flusso, simile a ciò che avviene quando si programma in Asp.Net,
-niente codice, quindi solo markup. In quest'ultimo caso si può anche non compilare.
Il markup viene definito in un file con estensione .xoml.
Giusto per dare un'idea di ciò che si può fare, possiamo per esempio, eseguire questo semplicissimo file XOML:
   1: <SequentialWorkflowActivity x:Class="SeqWF.Workflow3" x:Name="Workflow3" 
   2: xmlns:ns0="clr-namespace:ActivityLibrary;Assembly=ActivityLibrary, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null"
   3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
   5:     <ns0:MyActivity x:Name="MyActivity" />
   6: </SequentialWorkflowActivity>

Il contenuto del file è abbastanza parlante, si tratta di un flusso sequenziale con un custom activity MyActivity dell'assembly ActivityLibrary.
Questo activity non fa altro che scrivere nella finestra di Output di Visual Studio un semplice messaggio:
   1: public partial class MyActivity : System.Workflow.ComponentModel.Activity
   2: {
   3:   public MyActivity()
   4:   {
   5:     InitializeComponent();
   6:   }
   7:  
   8:   protected override ActivityExecutionStatus Execute(ActivityExecutionContext    executionContext)
   9:   {
  10:     System.Diagnostics.Debug.WriteLine("Esecuzione metodo");
  11:     return ActivityExecutionStatus.Closed;
  12:   }
  13: }
Non ci rimane che creare il workflow usando il file xoml appena visto:
   1: try
   2: {
   3:   //Folder contenente la dll dell'assembly ActivityLibrary e il file XOML
   4:   string path = "path dll Activity e file XOML";
   5:   WorkflowRuntime runtime = new WorkflowRuntime();
   6:   
   7:   ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService();
   8:   runtime.AddService(scheduler);
   9:  
  10:   TypeProvider typeProvider = new TypeProvider(runtime);
  11:   System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFrom(
  12:     System.IO.Path.Combine(path, "ActivityLibrary.dll"));
  13:   typeProvider.AddAssembly(ass);
  14:   runtime.AddService(typeProvider);
  15:  
  16:   runtime.StartRuntime();
  17:  
  18:   System.IO.StreamReader sr = new System.IO.StreamReader(
  19:     System.IO.Path.Combine(path, "Workflow3.xoml"));
  20:   System.Xml.XmlReader xml = System.Xml.XmlReader.Create(sr);
  21:   WorkflowInstance instance = runtime.CreateWorkflow(xml);
  22:  
  23:   instance.Start();
  24:   scheduler.RunWorkflow(instance.InstanceId);
  25: }
  26: catch (System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException exc)
  27: {
  28:   foreach (ValidationError err in exc.Errors)
  29:   {
  30:     string error = err.ErrorText;
  31:   }
  32: }

Il servizio TypeProvider si occupa di mantenere i riferimenti all'assembly del custom activity.
Per l'uso di un file xoml viene usato l'overload del metodo CreateWorkflow in cui invece di un tipo viene passato un oggetto XmlReader.
Con tale file Workflow3.xoml verrà lanciata la seguente eccezione:


x:Class cannot be used when the markup is executed directly without creating a new activity type

questo perchè l'attributo x:Class può essere presente solo quando il flusso viene compilato, ma in questo caso, di workflow con solo tag XAML deve essere eliminato.
Volendo è possibile ignorare errori di convalida, quando viene invocato il metodo CreateWorkflow, settando a false la property ValidateOnCreate:
   1: WorkflowRuntimeSection section = new WorkflowRuntimeSection();
   2: section.ValidateOnCreate = false;
   4: WorkflowRuntime runtime = new WorkflowRuntime( section);

Ovviamente così facendo sarà l'host a garantire la corretta configurazione del flusso di lavoro.

0 commenti:

Post a Comment