Compartir a través de


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

Footer image

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.