创建工作流宿主应用程序
宿主应用程序通过 WorkflowRuntime 类或从其继承的自定义类与 Windows Workflow Foundation 进行交互。 创建 WorkflowRuntime 对象,并用执行工作流的过程中将使用的服务填充该对象。
宿主应用程序责任
宿主应用程序的责任如下:
-
创建一个或多个进程以及一个或多个应用程序域。
-
根据需要提供隔离机制。
-
根据需要封送应用程序域之间的调用。
-
启动工作流实例。
-
创建自定义和本地服务。
此外,宿主应用程序还可能执行以下操作:
宿主应用程序必须执行的任务
添加和移除工作流服务
可以添加和移除工作流运行时中的服务。 可以使用在 WorkflowRuntime 类中定义的 AddService 方法添加服务。 使用同样在 WorkflowRuntime 类中定义的 RemoveService 方法移除服务。
向工作流运行时引擎添加服务
通过使用在 WorkflowRuntime 类中定义的 StartRuntime 方法开始执行工作流引擎之前,可以添加工作流所需的服务。 若要添加新服务,请创建服务对象的新实例,并调用在 WorkflowRuntime 类中定义的 AddService 方法,并传递服务对象作为参数。 下面的示例演示如何创建和启动运行时引擎、创建创建自定义跟踪服务中所述 EventLogTrackingService 服务的实例以及将该服务添加到工作流运行时引擎。
C# |
复制代码 |
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
namespace WorkflowApplication
{
class WorkflowHostExample
{
static void Main(string[] args)
{
// Create the runtime and EventLogTrackingService objects.
WorkflowRuntime runtime = new WorkflowRuntime();
EventLogTrackingService eventlogService = new EventLogTrackingService();
// Add the EventLogTrackingService and start the runtime.
runtime.AddService(eventlogService);
runtime.StartRuntime();
...
runtime.StopRuntime();
}
}
}
|
从工作流运行时引擎移除服务
如同可以向运行时引擎添加服务一样,也可以移除这些服务。 为此,要调用在 WorkflowRuntime 类中定义的 RemoveService 方法。 此方法的参数是要移除的服务的实例。 只有在工作流运行时引擎未运行的情况下才能移除服务。 因此,必须首先调用 StopRuntime 方法,移除服务,然后通过调用 StartRuntime 再次启动运行时。 下面的示例通过移除 EventLogTrackingService 服务对较早显示的示例进行了扩展。
C# |
复制代码 |
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
namespace WorkflowApplication
{
class WorkflowHostExample
{
static void Main(string[] args)
{
// Create the runtime and EventLogTrackingService objects.
WorkflowRuntime runtime = new WorkflowRuntime();
EventLogTrackingService eventlogService = new EventLogTrackingService();
// Add the EventLogTrackingService and start the runtime.
runtime.AddService(eventlogService);
runtime.StartRuntime();
...
// Stop the runtime and remove the EventLogTrackingService.
runtime.StopRuntime();
runtime.RemoveService(eventlogService);
}
}
|
注意: |
运行时引擎在运行过程中,无法移除运行时引擎自身所创建的任何服务。 运行时开始执行时就添加了这些默认服务,管理任何工作流的执行都需要这些服务。
|
运行时引擎在运行过程中,无法移除以下服务以及从这些类型派生的服务:
-
System.Workflow.Runtime.Hosting.WorkflowCommitWorkBatchService
-
System.Workflow.Runtime.Hosting.WorkflowPersistenceService
-
System.Workflow.Runtime.Tracking.TrackingService
-
System.Workflow.Runtime.Hosting.WorkflowSchedulerService
-
System.Workflow.Runtime.Hosting.WorkflowLoaderService
有关如何通过使用配置文件添加和移除服务的信息,请参见位于教程:承载 Windows Workflow Foundation 运行库和Workflow Configuration Formats中的任务 2:使用 App.Config 配置运行时服务。
对工作流应用工作流更改
动态更改正在运行的工作流实例的能力符合典型的人工工作流方案的要求。 例如,一个设置了四个面视官的面视工作流在运行时可能会进行更改,以添加第五个步骤来获取有关候选人的其他方面的考察的新信息。
这些工作流更改可以从工作流的执行线程内部和外部应用到正在运行的工作流实例。 在内部,通常是通过使用活动的事件处理程序来应用更改,或直接将更改应用到自定义活动的执行逻辑。 在外部,可以使用宿主应用程序中的 Windows Workflow Foundation API 来访问工作流并进行必要的更改。 为了确保工作流更改应用正确,宿主应该只在工作流实例处于挂起状态或保证处于空闲状态时应用工作流更改。
注意: |
工作流更改对于给定的工作流类型并非永久性更改,将不会传播到该类型将来的实例。
|
在工作流中创作
Windows Workflow Foundation 提供了 WorkflowChanges 类以方便在工作流中进行工作流更改。 可通过复合活动的 Add 方法添加活动,该复合活动将成为新添加的活动的父级。 相反,通过其父级复合活动的 Remove 方法可以移除一个活动。 这些更改在瞬态类中成批处理。
当执行工作流更改时,可以取消 Validate 方法。 Validate 方法将对活动图形执行语义检查,以确保在内存中锁定活动图形之前运行时语义的正确性。 然后可以从 WorkflowInstance 对象调用 ApplyWorkflowChanges 方法,并传递 WorkflowChanges 对象作为任何数量的相同工作流类型的参数。 但是,对于给定的瞬态类,只能在一个实例上调用一次 ApplyWorkflowChanges 方法。
下面的代码示例演示了如何使用 WorkflowChanges 类将更改添加到工作流实例。
C# |
复制代码 |
InvokeWorkflowActivity invokeNewWorkflow = new InvokeWorkflowActivity();
WorkflowChanges changes = new WorkflowChanges(this);
//
// NewWorkflow type
//
Type type = typeof(Workflow1);
invokeNewWorkflow.Name = "NewWorkflow";
invokeNewWorkflow.TargetWorkflow = type;
//
// Add NewWorkflow after delay.
//
DelayActivity delay = changes.TransientWorkflow.Activities["delay1"] as DelayActivity;
delay.Parent.Activities.Add(invokeNewWorkflow);
//
// Apply transient changes to instance.
//
this.ApplyWorkflowChanges(changes);
|
由于工作流的多个实例共享相同的活动树,因此,当发生动态更改时,将克隆活动树来进行更改,而其余的实例将继续共享原始的活动树。
从宿主环境中进行创作
WorkflowInstance 类公开 ApplyWorkflowChanges 方法以支持从工作流外部创作动态更改。 此方法大多数时间由宿主环境使用。
若要从宿主环境中将工作流更改应用到正在运行的工作流实例,请定位到要在其中进行工作流更改的实例并获取该实例的 WorkflowInstance。 运行库将针对每个工作流实例化创建一个 WorkflowInstance。 当调用 CreateWorkflow 时,宿主可以通过保存返回参数来获取工作流的 WorkflowInstance。
获取 WorkflowInstance 对象之后,创建一个 WorkflowChanges 对象并使用该对象的不同方法和属性来应用工作流更改。 执行此操作时,宿主使用的是 WorkflowInstance 的副本。 若要将工作流更改应用到当前正执行的 WorkflowInstance,请从 WorkflowInstance 对象调用 ApplyWorkflowChanges 方法。
有关从宿主动态更新工作流的示例,请参见Workflow Changes From Host。
工作流更改和活动属性
承载工作流设计器
虽然有 Windows Workflow Foundation 工作流可视化设计器的 Visual Studio 版本,但是可以在 Visual Studio 外部的 Windows 应用程序中承载工作流设计器。 您可以在自己的自定义 Windows 应用程序中承载基于图形的工作流设计器。 自定义应用程序可以实现具有基本设计器功能(如以图形方式显示预建工作流)的简单形式的工作流设计器,也可以实现具有更可靠功能集的工作流设计器版本(类似于 Visual Studio 版本的设计器)。
承载工作流设计器时必须使用的主要类如下:
-
.NET DesignSurface 类,该类通过提供一个完全独立的设计图面来实现用户心目中的设计器。
-
WorkflowView 类,该类显示在工作流标记中描述的工作流的可视化表示形式。
-
WorkflowDesignerLoader 类,该类支持对工作流设计器及其组件的加载进行自定义。
-
WorkflowDesignerMessageFilter 类,可以通过重写相应的虚拟方法从该类进行派生,以创建可处理拖动操作、布局和绘画操作等工作流设计器事件以及其他设计器事件的自定义消息筛选器。
Basic Designer Hosting示例演示如何使用这些类来创建在 Windows 应用程序中承载的工作流设计器的一个简单版本。
WorkflowDesigner 控件是Workflow Tracking Profile Designer的一部分,它为自定义工作流设计器宿主应用程序提供了很好的起点。 WorkflowDesigner 控件提供了一种在宿主应用程序中添加和扩展工作流设计器功能的简便方式。
添加菜单命令功能
由于工作流设计器是在 .NET Framework SDK 中的设计器基类的基础之上生成的,因此为了访问自定义应用程序中的菜单命令,必须从 MenuCommandService 类派生,重写其某些成员,然后将其作为服务添加到工作流加载程序对象所使用的设计器加载程序宿主。
下面的示例演示如何创建自定义 MenuCommandService。 在此示例中,当调用 ShowContextMenu 时会创建一个上下文菜单。 在 GetSelectionMenuItems 方法中,使用 WorkflowMenuCommands 类将工作流设计器提供的适当菜单命令与其对应文本相关联。 此操作完成后,将一个事件处理程序与每个命令相关联,以便在选择该命令时,调用相应的 MenuCommand。
下面的示例演示如何在从 WorkflowDesignerLoader 派生的类型上的 Initialize 重写方法中,将派生的 MenuCommandService 类型添加到设计器加载程序宿主。
下面是可在应用程序中使用的具有默认实现的命令:
-
Collapse
-
Copy
-
CopyToClipboard
-
CreateTheme
-
Cut
-
DefaultFilter
-
Delete
-
Disable
-
Enable
-
Expand
-
PageDown
-
PageSetup
-
PageUp
-
Pan
-
Paste
-
Print
-
PrintPreview
-
PrintPreviewPage
-
SaveAsImage
-
SelectAll
-
ShowAll
-
Zoom100Mode
-
Zoom150Mode
-
Zoom200Mode
-
Zoom300Mode
-
Zoom400Mode
-
Zoom50Mode
-
Zoom75Mode
-
ZoomIn
-
ZoomOut
WorkflowMenuCommands 和 StandardCommands 中的其余命令必须由您自己实现。
对于 Undo 和 MultiLevelUndo 等命令,必须从以下接口和类进行派生,并实现它们:
在创建这些派生的服务类之后,必须将它们添加到本节前面描述的经过重写的 Initialize 方法中。
另外,必须使用 AddCommand 方法将任何用户实现的命令添加到派生的 MenuCommandService 类型中,这样每当在设计器中访问该命令时,都会调用相应的事件处理程序。
有关更多信息,请参见 .NET Framework SDK 中的Extending Design-Time Support。
“设计器宿主”示例
下面的示例演示如何承载工作流设计器:
-
Basic Designer Hosting — 演示一个在 Windows 应用程序中承载的简单版本的工作流设计器。
-
Outlook Workflow Wizard — 使用 WorkflowView 类演示如何使用 Windows Workflow Foundation 工作流对象模型来创建可使用工作流设计器可视化的工作流定义。
-
Workflow Monitor — 演示如何使用工作流设计器来创建用于显示工作流和活动状态信息的工具。
-
Workflow Tracking Profile Designer — 演示如何使用 WorkflowDesigner 控件创建一个工具来支持从工作流定义创建跟踪配置文件。
将工作流部署为 Web 服务
Windows Workflow Foundation 框架支持 Web 服务互操作性。 该框架能够将工作流作为 Web 服务公开给 ASP.NET 客户端和其他工作流。 Windows Workflow Foundation 支持将工作流作为 ASP.NET Web 服务发布到在 Internet 信息服务 (IIS) 6.0 上运行 ASP.NET 的 Web 服务器或服务器场。 因为 Windows Workflow Foundation Web 服务支持以 ASP.NET 2.0 为基础,所以它继承了标准 ASP.NET Web 服务的大部分功能。
Windows Workflow Foundation 基本活动库包含 WebServiceInputActivity 和 WebServiceOutputActivity 活动,这些活动允许将工作流用作 Web 服务终结点。 有关使用这些 Web 服务活动的信息,请参见使用 WebServiceInputActivity 活动和使用 WebServiceOutputActivity 活动。
工作流 Web 承载
用于工作流 Web 承载的主要类包括:
WorkflowWebHostingModule
WorkflowWebHostingModule 类是默认的路由机制,用于通过使用 ASP.NET Cookie 将 Web 服务请求路由到相应的工作流。 当然,发出这些请求的客户端必须支持 Cookie。
虽然 Windows Workflow Foundation 提供此默认路由机制,但您可以实现自己的自定义路由机制。 例如,当不能在客户端中启用 Cookie 时,可以配置客户端创建具有特定 Id 的工作流实例,并在每个 Web 服务请求中传递该 Id。 可以使用 SOAP 或 HTTP 处理程序配置请求管线以截获调用,从标头信息中检索工作流实例 Id,然后将 HttpContext.Current.Items.Add("__WorkflowInstanceId__", workflowInstanceId)
设置为传入的 Id。
ManualWorkflowSchedulerService
ManualWorkflowSchedulerService 类是 WorkflowSchedulerService 的一个专用实现,它通过重用一个线程(该线程发出 ASP.NET Web 请求以运行工作流实例),对 ASP.NET 进程中生成的线程数进行控制。 这确保了工作流运行时中的活动线程数在任意时候都等于 ASP.NET 进程中的活动 Web 请求数。
公开为 Web 服务的工作流的限制
实例路由在 ASP.NET 会话的基础上工作。 作为 Web 服务的使用者,它需要支持 ASP.NET Cookie。
即使可以将“接收请求-发送响应”建模为工作流中的异步操作,ASP.NET 的常规限制仍适用于 Web 服务的使用者,即实例不能在未处理的请求-响应操作之间迁移进程。
启用 Cookie 以调用工作流 Web 服务
工作流 Web 服务使用 Cookie 跟踪状态。 如果将工作流发布为 Web 服务,则必须在调用它的客户端代码中启用 Cookie。 例如:
C# |
复制代码 |
CalculatorWorkflow_WebService service = new CalculatorWorkflow_WebService();
service.CookieContainer = new System.Net.CookieContainer();
|
这使您可以对“service”对象进行方法调用。
创建工作流宿主和服务时,应考虑以下相关安全事项:
-
详细测试跨团队或跨公司创作的宿主服务,然后才能将它们用作宿主的一部分。
-
宿主必须通过将数据存储区与访问控制列表 (ACL) 关联,来保护工作流实例和跟踪的所有数据存储区的安全。 ACL 是适用于某个对象的安全保护的列表。
-
宿主配置文件应与访问控制列表 (ACL) 关联以防止篡改。
-
宿主必须信任通过使用工作流运行时运行的工作流。
-
宿主应对安全主体进行身份验证。
-
宿主应保护用于计时器和状态保持的数据库的安全。
-
宿主必须信任正在跟踪的工作流。
-
将 null System.Security.Principal.WindowsIdentity 对象传入 RaiseEvent 方法对应于没有角色检查的匿名访问。
-
应在宿主级别上进行相应的访问检查,以保护对 WorkflowRoleCollection 的任何动态更改。
-
应单独指定或在一个中心位置指定 SQL 连接字符串。
-
SQL 脚本是配置的一部分,但不在安装时运行。
-
集成 SQL Server 安全应该用于默认 SQL 跟踪服务。
-
宿主环境应保护数据库、配置文件以及活动和工作流程序集的安全。
-
宿主应保护消息、队列和工作流实例数据的数据存储区的安全。
-
默认跟踪服务(例如 SQL 跟踪服务)应具有对跟踪数据库的完全访问权限。
-
跟踪服务负责将推送到它们的数据事件移动到对应的数据存储区。
-
宿主必须设置以 XML 格式存储的配置文件上的相应访问控件,或信任传递给宿主的配置文件对象。