Abrimos Visual Studio y creamos un nuevo proyecto de tipo Sequential Workflow Console Application al que llamaremos WorkflowSample2. Por defecto, Visual Studio nos deja en el diseñador visual de flujos de trabajo para Workflow1.cs. Si no es así, vamos al diseñador para Workflow1.cs. Agregamos las siguientes actividades:
- Tipo: CodeActivity – Nombre: codeActivity1 – Descripción: La vamos a utilizar para escribir la cadena "Actividad 1" a la salida de la consola.
- Tipo: SuspendActivity – Nombre: suspendActivity1 – Descripción: SuspendActivity suspende la ejecución de un flujo de trabajo. WorkflowRuntime levantará el evento WorkflowSuspended avisando que la instancia del flujo de trabajo ha entrado en estado de suspensión, lo que nos va a permitir hacer modificaciones al flujo de trabajo y luego resumir la ejecución.
- Tipo: SequenceActivity – Nombre: sequenceActivity1 – Descripción: SequenceActivity es una actividad compuesta que ejecuta actividades hijas en el orden en que fueron agregadas. En este caso, vamos a utilizarla como "placeholder" para agregar la nueva actividad.
- Tipo: CodeActivity – Nombre: codeActivity2 – Descripción: La vamos a utilizar para escribir la cadena "Actividad 3" a la salida de la consola.
Hacemos clic derecho sobre codeActivity1 y seleccionamos la opción de menú "Generate Handlers" (que nos crea un nuevo manejador para el evento ExecuteCode). Volvemos al diseñador y repetimos el mismo paso pero para la actividad codeActivity2.
Nos vamos a la vista de código y en los métodos generados (codeActivity1_ExecuteCode y codeActivity2_ExecuteCode) ponemos lo siguiente:
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Actividad 1");
}
private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Actividad 3");
}
Hecho esto, agregamos una nueva clase al proyecto que llamaremos "EscribirMensajeActivity". Cambiamos la declaración de la clase para que sea pública y la hacemos heredar de Activity (System.Workflow.ComponentModel.Activity).
Activity es la clase base para todas las actividades. El método principal en el que ponemos la lógica de ejecución es Execute y es llamado por el runtime de flujos de trabajo.
Sobrescribimos entonces el método Execute y ponemos lo siguiente:
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
Console.WriteLine(Mensaje);
return ActivityExecutionStatus.Closed;
}
Tenemos que crear un campo de tipo string llamado _Mensaje que va a servir como contenedor para la cadena que se va a escribir a la salida de la consola. Luego, creamos la propiedad para el campo _Mensaje.
private string _Mensaje;
public string Mensaje
{
get { return _Mensaje; }
set { _Mensaje = value; }
}
Por último vamos a hacer unas modificaciones al código que Visual Studio generó en Program.cs. Nos suscribimos al evento WorkflowSuspended de workflowRuntime:
static void Main(string[] args)
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
workflowRuntime.WorkflowSuspended +=
new EventHandler<WorkflowSuspendedEventArgs>(workflowRuntime_WorkflowSuspended);
...
En el método encargado de manejar el evento WorkflowSuspended (workflowRuntime_WorkflowSuspended) ponemos lo siguiente:
static void workflowRuntime_WorkflowSuspended(object sender, WorkflowSuspendedEventArgs e)
{
WorkflowChanges lWorkflowChanges =
new WorkflowChanges(e.WorkflowInstance.GetWorkflowDefinition());
EscribirMensajeActivity lEscribirMensajeActivity = new EscribirMensajeActivity();
lEscribirMensajeActivity.Mensaje = "Actividad 2";
((CompositeActivity)lWorkflowChanges.TransientWorkflow.Activities["sequenceActivity1"]).
Activities.Add(lEscribirMensajeActivity);
e.WorkflowInstance.ApplyWorkflowChanges(lWorkflowChanges);
e.WorkflowInstance.Resume();
}
Cuando queremos hacer cambios a un flujo de trabajo, los tenemos que hacer utilizando la clase WorkflowChanges que toma como parámetro la actividad raíz. En este caso la actividad raíz para la instancia del flujo de trabajo que queremos modificar la sacamos con el método GetWorkflowDefinition de WorkflowInstance que lo tenemos en "e" (WorkflowSuspendedEventArgs). Después, creamos una nueva instancia de nuestra actividad (EscribirMensajeActivity) y establecemos la propiedad Mensaje.
La propiedad TransientWorkflow de WorkflowChanges devuelve una copia exacta de la estructura del flujo de trabajo que vamos a utilizar para ubicar la actividad sequenceActivity1 que convertiremos a CompositeActivity para poder agregar la actividad hija.
Una vez agregada la actividad hija, llamamos al método ApplyWorkflowChanges de WorkflowInstance pasando la instancia de WorkflowChanges. Finalmente, llamamos al método Resume para continuar con la ejecución del flujo de trabajo.
Compilamos y ejecutamos. Deberíamos ver lo siguiente:
