玄铁剑

成功的途径:抄,创造,研究,发明...
posts - 128, comments - 42, trackbacks - 0, articles - 174

创建自定义跟踪服务

Posted on 2008-06-29 11:19 玄铁剑 阅读(197) 评论(0)  编辑 收藏 引用 所属分类: WF

Windows Workflow Foundation 包含多个服务,可以将这些服务插入宿主环境并立即开始使用。 但是,在某些情况下,可能必须对特定服务进行自定义或创建自己的服务。 使用跟踪服务可以将进程信息保持到存储介质,包括日志文件或 SQL Server 数据库等。 本主题详细介绍创建自定义的跟踪服务所需的步骤。

创建自定义跟踪服务类

接收跟踪数据的每个组件都必须派生自 TrackingService 基类。 宿主向 Windows Workflow Foundation 运行时注册跟踪服务,就像任何其他 Windows Workflow Foundation 服务一样。 注册跟踪服务之后,跟踪框架就可以识别该服务,并使该服务可以跟踪工作流实例执行。 有关如何注册服务的更多信息,请参见如何:添加和移除工作流服务

自定义跟踪服务是从抽象 TrackingService 类派生的类对象。 TrackingService 类包含多个抽象方法,必须重写这些方法才能提供自定义的跟踪服务行为。

例如,假设要创建使用系统事件日志输出跟踪信息的自定义跟踪服务。 若要开始,请在项目中创建新类,并将其命名为 EventLogTrackingService。 然后从 TrackingService 基类中派生类。

若要生成改写抽象基类方法所需的方法,请右击 TrackingService 类名,然后在快捷菜单中选择“实现抽象类‘TrackingService’”。 这样将生成用于实现自定义跟踪服务的方法定义。

您的代码应该类似于以下代码示例。

C#  CopyCode image复制代码
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.");
            }
            }
            }
Visual Basic  CopyCode image复制代码
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 对象,并将配置文件与 ActivityTrackPointActivityTrackingLocation 对象相关联。 通过调用以下示例所示对象的 TryGetProfile 方法,工作流运行时引擎会将工作流类型与跟踪配置文件相关联。 在此示例中,使用一个名为 GetDefaultProfile 的静态方法创建默认的跟踪配置文件。

Note注意:

调用 GetProfile 方法时,传入方法的版本号必须与要使用的跟踪配置文件的版本号相对应。 此外,在跟踪配置文件与用于 SqlTrackingService 服务的 UpdateTrackingProfile 存储过程之间,版本号必须相匹配。

Note注意:

下一节的结尾处提供实现 GetTrackingChannel 方法的示例。

C#  CopyCode image复制代码
// 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;
            }
Visual Basic  CopyCode image复制代码
' 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 参数提取数据以及将该信息输出到事件日志。

C#  CopyCode image复制代码
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");
            }
            }
            }
            }
Visual Basic  CopyCode image复制代码
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 方法返回该对象,如以下代码示例所示。

C#  CopyCode image复制代码
protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
            {
            return new EventLogTrackingChannel(parameters);
            }
Visual Basic  CopyCode image复制代码
Protected Overrides Function GetTrackingChannel(ByVal parameters As TrackingParameters) As TrackingChannel
            Return New EventLogTrackingChannel(parameters)
            End Function
只有注册用户登录后才能发表评论。