创建自定义跟踪服务
Windows Workflow Foundation 包含多个服务,可以将这些服务插入宿主环境并立即开始使用。 但是,在某些情况下,可能必须对特定服务进行自定义或创建自己的服务。 使用跟踪服务可以将进程信息保持到存储介质,包括日志文件或 SQL Server 数据库等。 本主题详细介绍创建自定义的跟踪服务所需的步骤。
创建自定义跟踪服务类
接收跟踪数据的每个组件都必须派生自 TrackingService 基类。 宿主向 Windows Workflow Foundation 运行时注册跟踪服务,就像任何其他 Windows Workflow Foundation 服务一样。 注册跟踪服务之后,跟踪框架就可以识别该服务,并使该服务可以跟踪工作流实例执行。 有关如何注册服务的更多信息,请参见如何:添加和移除工作流服务。
自定义跟踪服务是从抽象 TrackingService 类派生的类对象。 TrackingService 类包含多个抽象方法,必须重写这些方法才能提供自定义的跟踪服务行为。
例如,假设要创建使用系统事件日志输出跟踪信息的自定义跟踪服务。 若要开始,请在项目中创建新类,并将其命名为 EventLogTrackingService。 然后从 TrackingService 基类中派生类。
若要生成改写抽象基类方法所需的方法,请右击 TrackingService 类名,然后在快捷菜单中选择“实现抽象类‘TrackingService’”。 这样将生成用于实现自定义跟踪服务的方法定义。
您的代码应该类似于以下代码示例。
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
跟踪配置文件
从 TrackingService 基类中必须重写的抽象方法涉及到使用 TrackingProfile 和 TrackingChannel。 有关如何使用 TrackingProfile 的更多信息,请参见创建和使用跟踪配置文件。 有关 TrackingService 类的更多信息,请参见 TrackingService。
打开通道以将跟踪数据传输到跟踪服务之前,必须提供配置文件。 此配置文件说明跟踪服务需要从运行时引擎接收的跟踪数据的类型。 为此,请创建新的 TrackingProfile 对象,并将配置文件与 ActivityTrackPoint 和 ActivityTrackingLocation 对象相关联。 通过调用以下示例所示对象的 TryGetProfile 方法,工作流运行时引擎会将工作流类型与跟踪配置文件相关联。 在此示例中,使用一个名为 GetDefaultProfile 的静态方法创建默认的跟踪配置文件。
备注
调用 GetProfile 方法时,传入方法的版本号必须与要使用的跟踪配置文件的版本号相对应。 此外,在跟踪配置文件与用于 SqlTrackingService 服务的 UpdateTrackingProfile 存储过程之间,版本号必须相匹配。
备注
下一节的结尾处提供实现 GetTrackingChannel 方法的示例。
// 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
实现 TrackingChannel
TrackingChannel 抽象类充当为单个工作流实例接收跟踪事件和数据的管道。 TrackingChannel 的用途是为跟踪服务编写器提供一种机制,用以接收跟踪信息,而不必考虑线程的安全性。 由于每个工作流实例只有一个执行线程,因此在 TrackingChannel 对象中不会同时有一个以上的线程处于活动状态。 这样可以降低对数据同步的需要。
TrackingChannel 是用于在工作流和您的跟踪服务之间进行通信的对象。 若要为 EventLogTrackingService 创建 TrackingChannel,请创建 EventLogTrackingChannel 类,从 TrackingChannel 基类派生类,并实现所需的抽象方法,就像上一节中对 TrackingService 抽象类所做的那样。
工作流通过在 TrackingChannel 类中定义的 Send 方法发送跟踪信息。 将 TrackingRecord 作为参数传递,从中可以提取跟踪信息。 以下代码示例演示如何从 ActivityRecord 参数提取数据以及将该信息输出到事件日志。
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
工作流运行时引擎通过调用在 EventLogTrackingService 类中定义的 GetTrackingChannel 方法,获取 EventLogTrackingChannel 的引用。 创建新的 EventLogTrackingChannel 对象,并从 GetTrackingChannel 方法返回该对象,如以下代码示例所示。
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
请参见
参考
TrackingService
TrackingChannel
TrackingProfile
概念
其他资源
ConsoleTrackingService Sample
Tracking Profile Designer Sample
开发 Windows Workflow Foundation 服务
版权所有 (C) 2007 Microsoft Corporation。保留所有权利。