Condividi tramite


Creare servizi di rilevamento personalizzati

Windows Workflow Foundation contiene molti servizi che è possibile collegare all'ambiente host e cominciare ad utilizzare immediatamente. In alcune istanze, tuttavia, è necessario personalizzare un particolare servizio o crearne uno su misura. I servizi di rilevamento consentono di salvare in modo permanente informazioni sui processi in un supporto di archiviazione, inclusi elementi come file di log o database SQL Server. Questo argomento descrive i passaggi necessari per creare un servizio di rilevamento personalizzato.

Creazione della classe del servizio del rilevamento personalizzato

Ogni componente che riceve dati di rilevamento deve derivare dalla classe di base TrackingService. L'host registra servizi di rilevamento con il runtime di Windows Workflow Foundation come qualsiasi altro servizio di Windows Workflow Foundation. Dopo la registrazione di un servizio di rilevamento, il framework di rilevamento lo riconosce e gli consente di registrare l'esecuzione delle istanze del flusso di lavoro. Per ulteriori informazioni sulle modalità di registrazione dei servizi, vedere Procedura: aggiungere e rimuovere servizi del flusso di lavoro.

Un servizio di rilevamento personalizzato è un oggetto di classe che deriva dalla classe astrattaTrackingService. La classe TrackingService contiene molti metodi astratti che è necessario ignorare per stabilire il comportamento del servizio di rilevamento personalizzato.

Per esempio, supporre di voler creare un servizio di rilevamento personalizzato che utilizza il registro eventi di sistema per restituire informazioni di rilevamento. Per iniziare, creare una nuova classe nel progetto e denominarla EventLogTrackingService. Derivare la classe dalla classe baseTrackingService.

Per generare i metodi necessari per eseguire l'override dei metodi della classe di base astratta, fare clic con il pulsante destro del mouse sul nome della classe TrackingService e selezionare Implementa classe astratta 'TrackingService' nel menu di scelta rapida. Genera le definizioni del metodo che si utilizzano per implementare il servizio di rilevamento personalizzato.

Il codice dovrebbe risultare simile al seguente esempio di codice:

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

Profili di rilevamento

I metodi astratti dalla classe di base TrackingService che è necessario ignorare sono TrackingProfiles e TrackingChannels. Per ulteriori informazioni sulle modalità di utilizzo di TrackingProfiles, vedere Creazione e utilizzo di profili di rilevamento. Per ulteriori informazioni sulla classe TrackingService, vedere TrackingService.

Prima che venga aperto un canale per la trasmissione di dati di rilevamento al servizio di rilevamento, è necessario fornire un profilo. Il profilo descrive il tipo di dati di rilevamento che il servizio di rilevamento deve ricevere dal motore di runtime. A questo scopo, creare un nuovo oggetto TrackingProfile e associare il profilo agli oggetti ActivityTrackPoint e ActivityTrackingLocation. Il motore di runtime del flusso di lavoro assocerà tipi di flusso di lavoro ai profili di rilevamento chiamando il metodo TryGetProfile dell'oggetto, come mostra l'esempio seguente. In questo esempio, viene utilizzato un solo metodo statico denominato GetDefaultProfile per creare un profilo di rilevamento predefinito.

Nota

Quando si chiama il metodo GetProfile, il numero di versione che si passa nel metodo deve corrispondere al numero di versione del profilo di rilevamento che si desidera utilizzare. Inoltre, il numero di versione del profilo di rilevamento e della stored procedure UpdateTrackingProfile utilizzati con il servizio SqlTrackingService devono corrispondere.

Nota

L'implementazione di esempio per il metodo GetTrackingChannel viene fornita alla fine della prossima sezione.

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

Implementazione di TrackingChannel

La classe astratta TrackingChannel serve da condotto per ricevere eventi di rilevamento e dati per una sola istanza del flusso di lavoro. Lo scopo di TrackingChannel è fornire un meccanismo affinché i writer del servizio di rilevamento ricevano informazioni di rilevamento senza dovere considerare la protezione dei thread. Poiché ogni istanza del flusso di lavoro ha solo uno thread di esecuzione, non c'è mai più di un thread attivo in un oggetto TrackingChannel. Ciò riduce la necessità di sincronizzare i dati.

TrackingChannel è l'oggetto utilizzato per la comunicazione tra il flusso di lavoro e il servizio di rilevamento. Per creare un oggetto TrackingChannel per EventLogTrackingService, creare una classe EventLogTrackingChannel, dedurre la classe dalla classe di base TrackingChannel e implementare i metodi astratti obbligatori come effettuato per la classe astratta TrackingService nella sezione precedente.

Quando un flusso di lavoro invia informazioni di rilevamento, lo fa tramite il metodo Send definito nella classe TrackingChannel. Una classe TrackingRecord è passata come parametro dal quale è possibile estrarre le informazioni di rilevamento. Nell'esempio di codice seguente viene illustrato come estrarre dati dal parametro ActivityRecord e restituire le informazioni al registro eventi.

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

Il motore di runtime del flusso di lavoro ottiene un riferimento per EventLogTrackingChannel chiamando il metodo GetTrackingChannel definito nella classe EventLogTrackingService. Creare un nuovo oggetto EventLogTrackingChannel e restituire l'oggetto dal metodo GetTrackingChannel come mostra l'esempio di codice seguente.

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

Vedere anche

Riferimenti

TrackingService
TrackingChannel
TrackingProfile

Concetti

Procedura: aggiungere e rimuovere servizi del flusso di lavoro
Creazione e utilizzo di profili di rilevamento

Altre risorse

ConsoleTrackingService Sample
Tracking Profile Designer Sample
Sviluppo dei servizi di Windows Workflow Foundation

Footer image

Copyright © 2007 Microsoft Corporation. Tutti i diritti riservati.