Creación de los servicios de seguimiento personalizados
Windows Workflow Foundation contiene varios servicios que puede conectar en su entorno host y empezar a usar inmediatamente. En algunas instancias, sin embargo, puede tener que personalizar un servicio determinado o crear su propio. Los servicios de seguimiento le permiten conservar información de proceso en medios de almacenamiento, incluso tales cosas como un archivo de registro o una base de datos de SQL Server. En este tema se detallan los pasos que se exigen para crear su propio servicio de seguimiento personalizado.
Creación de la clase de servicio de seguimiento personalizado
Cada componente que recibe datos de seguimiento debe derivar de la clase base TrackingService. El host registra los servicios de seguimiento con el tiempo de ejecución de Windows Workflow Foundation como cualquier otro servicio de Windows Workflow Foundation. Una vez registrado un servicio de seguimiento, el marco de seguimiento lo reconoce y le permite realizar el seguimiento de la ejecución de la instancia de flujo de trabajo. Para obtener más información acerca de cómo registrar servicios, consulte Cómo agregar y quitar servicios de flujo de trabajo.
Un servicio de seguimiento personalizado es un objeto de clase que deriva de la clase TrackingService abstracta. La clase TrackingService contiene varios métodos abstractos que debe invalidar para proporcionar su comportamiento de servicio de seguimiento personalizado.
Como ejemplo, suponga que desea crear un servicio de seguimiento personalizado que utiliza el registro de evento de sistema para generar información de seguimiento. Para iniciar, cree una nueva clase en su proyecto y denomínela EventLogTrackingService. Derive la clase de la clase base TrackingService.
Para generar los métodos necesarios para invalidar los métodos de clase base abstracta, haga clic con el botón secundario en el nombre de clase TrackingService y seleccione Implementar clase abstracta 'TrackingService' en el menú de acceso directo. Esto genera las definiciones de método que utiliza para implementar su servicio de seguimiento personalizado.
Su código debería asemejarse al siguiente:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Tracking;
namespace CustomTrackingService
{
public class EventLogTrackingService : TrackingService
{
protected override TrackingProfile GetProfile(Guid workflowInstanceId)
{
throw new Exception("The method or operation is not implemented.");
}
protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
{
throw new Exception("The method or operation is not implemented.");
}
protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
{
throw new Exception("The method or operation is not implemented.");
}
protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
{
throw new Exception("The method or operation is not implemented.");
}
protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
{
throw new Exception("The method or operation is not implemented.");
}
}
}
Imports System
Imports System.Diagnostics
Imports System.Collections.Generic
Imports System.Text
Imports System.Threading
Imports System.Workflow.ComponentModel
Imports System.Workflow.Runtime
Imports System.Workflow.Runtime.Tracking
Public Class EventLogTrackingService
Inherits TrackingService
Protected Overloads Overrides Function GetProfile(ByVal workflowInstanceId As System.Guid) As System.Workflow.Runtime.Tracking.TrackingProfile
End Function
Protected Overloads Overrides Function GetProfile(ByVal workflowType As System.Type, ByVal profileVersionId As System.Version) As System.Workflow.Runtime.Tracking.TrackingProfile
End Function
Protected Overrides Function GetTrackingChannel(ByVal parameters As System.Workflow.Runtime.Tracking.TrackingParameters) As System.Workflow.Runtime.Tracking.TrackingChannel
End Function
Protected Overrides Function TryGetProfile(ByVal workflowType As System.Type, ByRef profile As System.Workflow.Runtime.Tracking.TrackingProfile) As Boolean
End Function
Protected Overrides Function TryReloadProfile(ByVal workflowType As System.Type, ByVal workflowInstanceId As System.Guid, ByRef profile As System.Workflow.Runtime.Tracking.TrackingProfile) As Boolean
End Function
End Class
Perfiles de seguimiento
Los métodos abstractos que debe invalidar de la clase base TrackingService incluyen trabajar con TrackingProfiles y TrackingChannels. Para obtener más información acerca de cómo usar TrackingProfiles, consulte Creación y uso de perfiles de seguimiento. Para obtener más información sobre la clase TrackingService, consulte TrackingService.
Antes de que un canal se abra para la transmisión de datos de seguimiento a su servicio de seguimiento, debe proporcionar un perfil. Este perfil describe el tipo de datos de seguimiento que su servicio de seguimiento desea recibir del motor de tiempo de ejecución. Para ello, cree un nuevo objeto TrackingProfile y asocie el perfil a los objetos ActivityTrackPoint y ActivityTrackingLocation. El motor de tiempo de ejecución de flujo de trabajo asociará los tipos de flujo de trabajo con perfiles de seguimiento llamando al método TryGetProfile de su objeto como se muestra en el ejemplo siguiente. En este ejemplo se usa un método estático único denominado GetDefaultProfile para crear un perfil de seguimiento predeterminado.
Nota
Al llamar al método GetProfile, el número de versión que pasa al método debe corresponder al número de versión del perfil de seguimiento que desea utilizar. Asimismo, el número de versión debe coincidir entre el perfil de seguimiento y el procedimiento UpdateTrackingProfile almacenado que se utiliza con el servicio SqlTrackingService.
Nota
La implementación del ejemplo para el método GetTrackingChannel se proporciona al final de la sección siguiente.
// Add in a local variable and overloaded constructor methods.
protected WorkflowRuntime runtimeContainer = null;
public EventLogTrackingService()
{
}
public EventLogTrackingService (WorkflowRuntime container)
{
runtimeContainer = container;
}
// Implement the TrackingService abstract methods.
protected override TrackingProfile GetProfile(Guid workflowInstanceId)
{
// Instance profiles not implemented.
throw new NotImplementedException("The method or operation is not implemented.");
}
protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
{
return GetDefaultProfile();
}
protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
{
// Depending on the workflowType, service can return different
// tracking profiles. In this sample, the same profile is returned
// for all running types.
profile = GetDefaultProfile();
return true;
}
protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
{
// Reloading profiles not implemented.
profile = null;
return false;
}
// Create the profile.
private static TrackingProfile GetDefaultProfile()
{
TrackingProfile profile = new TrackingProfile();
profile.Version = new Version("3.0.0");
// Add activity track points.
ActivityTrackPoint atp = new ActivityTrackPoint();
ActivityTrackingLocation location = new ActivityTrackingLocation(typeof(Activity));
location.MatchDerivedTypes = true;
foreach (ActivityExecutionStatus s in Enum.GetValues(typeof(ActivityExecutionStatus)))
{
location.ExecutionStatusEvents.Add(s);
}
atp.MatchingLocations.Add(location);
profile.ActivityTrackPoints.Add(atp);
// Add instance track points.
WorkflowTrackPoint wtp = new WorkflowTrackPoint();
WorkflowTrackingLocation workflowLocation = new WorkflowTrackingLocation();
wtp.MatchingLocation = workflowLocation;
foreach (TrackingWorkflowEvent workflowEvent in Enum.GetValues(typeof(TrackingWorkflowEvent)))
{
wtp.MatchingLocation.Events.Add(workflowEvent);
}
profile.WorkflowTrackPoints.Add(wtp);
return profile;
}
' Add in a local variable and overloaded constructor methods.
Protected runtimeContainer As WorkflowRuntime = Nothing
Public Sub New()
End Sub
Public Sub New(ByVal container As WorkflowRuntime)
runtimeContainer = container
End Sub
' Implement the TrackingService abstract methods.
Protected Overloads Overrides Function GetProfile(ByVal workflowInstanceId As Guid) As TrackingProfile
' Instance profiles not implemented
Throw New NotImplementedException("The method or operation is not implemented.")
End Function
Protected Overloads Overrides Function GetProfile(ByVal workflowType As Type, ByVal profileVersionId As Version) As TrackingProfile
Return GetDefaultProfile()
End Function
Protected Overrides Function TryGetProfile(ByVal workflowType As Type, ByRef profile As TrackingProfile) As Boolean
' Depending on the workflowType, service can return different
' tracking profiles. In this sample, the same profile is returned
' for all running types.
profile = GetDefaultProfile()
Return True
End Function
Protected Overrides Function TryReloadProfile(ByVal workflowType As Type, ByVal workflowInstanceId As Guid, ByRef profile As TrackingProfile) As Boolean
' Reloading profiles not implemented.
profile = Nothing
Return False
End Function
' Create the profile.
Private Shared Function GetDefaultProfile() As TrackingProfile
Dim profile As New TrackingProfile()
profile.Version = New Version("3.0.0")
' Add activity track points.
Dim atp As New ActivityTrackPoint()
Dim location As New ActivityTrackingLocation(GetType(Activity))
location.MatchDerivedTypes = True
Dim s As ActivityExecutionStatus
For Each s In System.Enum.GetValues(GetType(ActivityExecutionStatus))
location.ExecutionStatusEvents.Add(s)
Next s
atp.MatchingLocations.Add(location)
profile.ActivityTrackPoints.Add(atp)
' Add instance track points.
Dim wtp As New WorkflowTrackPoint()
Dim workflowLocation As New WorkflowTrackingLocation()
wtp.MatchingLocation = workflowLocation
Dim workflowEvent As TrackingWorkflowEvent
For Each workflowEvent In System.Enum.GetValues(GetType(TrackingWorkflowEvent))
wtp.MatchingLocation.Events.Add(workflowEvent)
Next workflowEvent
profile.WorkflowTrackPoints.Add(wtp)
Return profile
End Function
Implementación de TrackingChannel
La clase abstracta TrackingChannel actúa como una canalización que recibe eventos de seguimiento y datos para una instancia de flujo de trabajo única. El propósito de TrackingChannel es proporcionar un mecanismo para que los escritores de servicio de seguimiento reciban información de seguimiento sin tener que considerar la seguridad de los subprocesos. Dado que cada instancia de flujo de trabajo tiene solo un subproceso de ejecución, nunca hay más de un subproceso activo al mismo tiempo en un TrackingChannel objeto. Esto reduce la necesidad de sincronización de datos.
TrackingChannel es el objeto que se utiliza para la comunicación entre el flujo de trabajo y su servicio de seguimiento. Para crear un TrackingChannel para EventLogTrackingService, cree una clase EventLogTrackingChannel, derive la clase de la clase base TrackingChannel e implemente los métodos abstractos necesarios tal y como hizo para la clase abstracta TrackingService en la sección anterior.
Cuando un flujo de trabajo envía información de seguimiento, lo hace a través del método Send que se define en su clase TrackingChannel. TrackingRecord se pasa como un parámetro del que puede extraer información de seguimiento. El ejemplo de código siguiente muestra cómo extraer datos del parámetro ActivityRecord y generar esa información en el registro de eventos.
public class EventLogTrackingChannel : TrackingChannel
{
// Add in a local variable and constructor method.
private TrackingParameters parameters = null;
public EventLogTrackingChannel(TrackingParameters parameters)
{
this.parameters = parameters;
}
// InstanceCompletedOrTerminated is called by Tracking runtime to
// indicate that the Workflow instance finished running.
protected override void InstanceCompletedOrTerminated()
{
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow Instance Completed or Terminated");
}
// Implement the TrackingChannel abstract methods.
protected override void Send(TrackingRecord record)
{
if (record is ActivityTrackingRecord)
{
ActivityTrackingRecord act = (ActivityTrackingRecord)record;
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Activity: " + act.QualifiedName + " - " + act.ExecutionStatus );
}
else if (record is WorkflowTrackingRecord)
{
if (TrackingWorkflowEvent.Changed == ((WorkflowTrackingRecord)record).TrackingWorkflowEvent)
{
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow changes have been applied");
}
}
}
}
Public Class EventLogTrackingChannel
Inherits TrackingChannel
' Add in a local variable and constructor method.
Private parameters As TrackingParameters = Nothing
Public Sub New(ByVal parameters As TrackingParameters)
Me.parameters = parameters
End Sub
' InstanceCompletedOrTerminated is called by Tracking runtime to
' indicate that the Workflow instance finished running.
Protected Overrides Sub InstanceCompletedOrTerminated()
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow Instance Completed or Terminated")
End Sub
' Implement the TrackingChannel abstract methods.
Protected Overrides Sub Send(ByVal record As System.Workflow.Runtime.Tracking.TrackingRecord)
If TypeOf record Is ActivityTrackingRecord Then
Dim act As ActivityTrackingRecord = CType(record, ActivityTrackingRecord)
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Activity: " & act.QualifiedName & " - " & act.ExecutionStatus)
ElseIf TypeOf record Is WorkflowTrackingRecord Then
If TrackingWorkflowEvent.Changed = CType(record, WorkflowTrackingRecord).TrackingWorkflowEvent Then
System.Diagnostics.EventLog.WriteEntry("EventLogTrackingService", "Workflow changes have been applied")
End If
End If
End Sub
End Class
El motor de tiempo de ejecución de flujo de trabajo obtiene una referencia para su EventLogTrackingChannel llamando al método GetTrackingChannel definido en su clase EventLogTrackingService. Cree un nuevo objeto EventLogTrackingChannel y devuelva ese objeto del método GetTrackingChannel como se muestra en el ejemplo de código siguiente.
protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
{
return new EventLogTrackingChannel(parameters);
}
Protected Overrides Function GetTrackingChannel(ByVal parameters As TrackingParameters) As TrackingChannel
Return New EventLogTrackingChannel(parameters)
End Function
Consulte también
Referencia
TrackingService
TrackingChannel
TrackingProfile
Conceptos
Cómo agregar y quitar servicios de flujo de trabajo
Creación y uso de perfiles de seguimiento
Otros recursos
ConsoleTrackingService Sample
Tracking Profile Designer Sample
Desarrollo de servicios de Windows Workflow Foundation
Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.