Partager via


Création de services de suivi personnalisés

Windows Workflow Foundation contient plusieurs services qui vous pouvez intégrer à votre environnement d'hébergement et commencer à utiliser immédiatement. Toutefois, vous devrez peut-être personnaliser un service particulier dans certaines instances ou en créer. Les services de suivi vous permettent de rendre des informations sur le processus persistantes à un support de stockage, y compris des choses comme un fichier journal ou une base de données SQL Server. Cette rubrique détaille les étapes requises pour créer votre propre service de suivi personnalisé.

Création de la classe de service de suivi personnalisé

Chaque composant qui reçoit des données de suivi doit dériver de la classe de base TrackingService. L'hôte enregistre des services de suivi avec l'exécution de Windows Workflow Foundation comme tout autre service de Windows Workflow Foundation. Après avoir enregistré un service de suivi, l'infrastructure de suivi le reconnaît et l'autorise à suive l'exécution de l'instance de workflow. Pour plus d'informations sur l'enregistrement des services, consultez Comment : ajouter et supprimer des services de workflow.

Un service de suivi personnalisé est un objet de classe qui dérive de la classe TrackingService abstraite. La classe TrackingService contient plusieurs méthodes abstraites que vous devez substituer pour fournir votre comportement de service de suivi personnalisé.

Par exemple, supposons que vous souhaitez créer un service de suivi personnalisé qui utilise le journal des événements système pour renvoyer les informations de suivi. Pour commencer, créez une classe dans votre projet et nommez-la EventLogTrackingService. Dérivez cette classe de la classe de base TrackingService.

Pour générer les méthodes requises pour substituer les méthodes de classe de base abstraite, cliquez avec le bouton droit de la souris sur le nom de la classe TrackingService et sélectionnez Implémenter la classe abstraite « TrackingService » dans le menu contextuel. Cela génère les définitions de méthode que vous utilisez pour implémenter votre service de suivi personnalisé.

Le code doit apparaître comme l'exemple de code suivant.

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

Suivis de profil

Les méthodes abstraites que vous devez substituer de la classe de base TrackingService incluent l'utilisation de TrackingProfiles et TrackingChannels. Pour plus d'informations sur l'utilisation de TrackingProfiles, consultez Création et utilisation de profils de suivi. Pour plus d'informations sur la classe TrackingService, consultez TrackingService.

Avant qu'un canal soit ouvert pour la transmission du suivi des données vers votre service de suivi, vous devez fournir un profil. Ce profil décrit le type de suivi des données que votre service de suivi souhaite recevoir du moteur d'exécution. Pour cela, créez un objet TrackingProfile et associez le profil aux objets ActivityTrackPoint et ActivityTrackingLocation. Le moteur d'exécution de workflow associera des types de workflow avec les suivis de profil en appelant la méthode TryGetProfile de votre objet comme dans l'exemple suivant. Dans cet exemple, une méthode statique unique nommée GetDefaultProfile est utilisée pour créer un suivi de profil par défaut.

NoteRemarque :

Lorsque vous appelez la méthode GetProfile, le numéro de version que vous passez dans la méthode doit correspondre à celui du suivi de profil que vous souhaitez utiliser. De plus, le numéro de version doit correspondre entre le suivi de profil et la procédure stockée UpdateTrackingProfile utilisée avec le service SqlTrackingService.

NoteRemarque :

L'exemple d'implémentation de la méthode GetTrackingChannel est fourni à la fin de la section suivante.

// 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

Implémentation de TrackingChannel

La classe abstraite TrackingChannel sert de conduit qui reçoit des événements et des données de suivi pour une instance de workflow unique. Le but de TrackingChannel est de fournir un mécanisme permettant aux enregistreurs de service de suivi de recevoir des informations de suivi sans avoir à tenir compte de la sécurité des threads. Chaque instance de workflow possédant un seul thread d'exécution, il n'y a jamais plus d'un thread actif dans un objet TrackingChannel à la fois. Cela réduit le besoin de synchronisation de données.

TrackingChannel est l'objet utilisé pour la communication entre le workflow et votre service de suivi. Pour créer un TrackingChannel pour le EventLogTrackingService, créez une classe EventLogTrackingChannel, dérivez-la de la classe de base TrackingChannel et implémentez les méthodes abstraites requises comme vous l'avez fait pour la classe abstraite TrackingService dans la section précédente.

Lorsqu'un workflow envoie des informations de suivi, il le fait via la méthode Send définie dans votre classe TrackingChannel. Un TrackingRecord est passé comme paramètre duquel vous pouvez extraire les informations de suivi. L'exemple de code suivant montre comment renvoyer des données vers le paramètre ActivityRecord et exporter ces informations vers le journal des événements.

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

Le moteur d'exécution de workflow obtient une référence pour votre EventLogTrackingChannel en appelant la méthode GetTrackingChannel définie dans votre classe EventLogTrackingService. Créez un objet EventLogTrackingChannel et retournez cet objet de la méthode GetTrackingChannel comme dans l'exemple de code suivant.

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

Voir aussi

Référence

TrackingService
TrackingChannel
TrackingProfile

Concepts

Comment : ajouter et supprimer des services de workflow
Création et utilisation de profils de suivi

Autres ressources

ConsoleTrackingService Sample
Tracking Profile Designer Sample
Développement de services Windows Workflow Foundation

Footer image

Copyright ©2007 par Microsoft Corporation. Tous droits réservés.