Windows Workflow Foundation (WF)中顺序工作流是非常常用的一种工作流,而在工作流运行过程中通常会和宿主程序之间交换数据,用于从外部环境获取数据,同时将工作流的状态告诉外部环境。
工作流中用来达到此目的的activity有:WebServiceInput、WebServiceOutput、InvokeWebService、CallExternalMethod、HandleExternalEvent。前三个用于和WebServices交换数据,后两个用于本地的通讯。CallExternalMethod activity允许工作流来调用宿主中注册的程序,而HandleExternalEvent activity是让工作流通过宿主来监听对应的事件。
使用CallExternalMethod、HandleExternalEvent一般需要根据以下步骤:(以下借用《Programming Windows Workflow Foundation》中代码)
1、定义接口事件和相关的参数类型。
用ExternalDataExchange标签定义接口和事件。用Serializable标签定义参数类型。
[ExternalDataExchange]
public interface IBugFlowService
{
event EventHandler<BugAddedArgs> BugAdded;
void AssignBug(Bug bug);
}
[Serializable]
public class BugAddedArgs : ExternalDataEventArgs
{
private Bug _bug;
<span class="kwrd">public</span> BugAddedArgs(Guid instanceId, Bug newBug):<span class="kwrd">base</span>(instanceId)
{
_bug = newBug;
}
<span class="kwrd">public</span> Bug NewBug
{
get
{
<span class="kwrd">return</span> _bug;
}
set
{
_bug = <span class="kwrd">value</span>;
}
}
}
2、定义传送的对象
这一步也可以放在之前或其他文件中,但对象必须打上Serializable标签。
[Serializable]
public class Bug
{
private string _description;
private int _id;
private string _title;
<span class="kwrd">public</span> Bug(<span class="kwrd">int</span> id, <span class="kwrd">string</span> title, <span class="kwrd">string</span> description)
{
_id=id;
_title = title;
_description = description;
}
<span class="kwrd">public</span> <span class="kwrd">string</span> Descrition
{
get { <span class="kwrd">return</span> _description; }
set { _description = <span class="kwrd">value</span>;}
}
<span class="kwrd">public</span> <span class="kwrd">int</span> ID
{
get { <span class="kwrd">return</span> _id; }
set { _id = <span class="kwrd">value</span>;}
}
<span class="kwrd">public</span> <span class="kwrd">string</span> Title
{
get { <span class="kwrd">return</span> _title;}
set{_title = <span class="kwrd">value</span>;}
}
}</pre>
3、实现约定的接口
实现第一步中约定的服务接口
public class BugFlowService : IBugFlowService
{
public event EventHandler<BugAddedArgs> BugAdded;
<span class="kwrd">public</span> <span class="kwrd">void</span> AssignBug(Bug bug)
{
Console.WriteLine(<span class="str">"Assign '{0}' to developer"</span>, bug.Title);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> CreateBug(Guid instanceID, Bug bug)
{
BugAddedArgs arg = <span class="kwrd">new</span> BugAddedArgs(instanceID, bug);
EventHandler<BugAddedArgs> ev = <span class="kwrd">this</span>.BugAdded;
<span class="kwrd">if</span> (ev != <span class="kwrd">null</span>)
{
ev(<span class="kwrd">null</span>, arg);
}
}
}
4、设计工作流及参数
新建一个顺序工作流,并依次从ToolsBox中拖放HandleExternalEvent activity、CallExternalMethod activity。分别命名NewBug、AssignBug。
设置命名为NewBug的HandleExternalEvent activity的InterfaceType属性为IBugFlowService,指定EventName属性为BugAdded,设置e参数来代表传入的事件参数,点击右侧的省略号按钮来绑定(或创建并绑定)参数到公开域或属性(例如:_newBug)。
设置命名为AssignBug的CallExternalMethod activity的InterfaceType属性为IBugFlowService,指定MethodName属性为AssignBug,AssignBug需要一个参数bug,点击bug参数右侧的省略号按钮来绑定(或创建并绑定)参数到公开域或属性(例如:_bugToAssign),为MethodInvoking事件生成事件处理方法AssignBug_MethodInvoking。
public Bug _bugToAssign;
public BugAddedArgs _newBug;
<span class="kwrd">private</span> <span class="kwrd">void</span> AssignBug_MethodInvoking(<span class="kwrd">object</span> sender, EventArgs e)
{
_bugToAssign = _newBug.NewBug;
}</pre>
5、在宿主中执行工作流
修改宿主启动工作流地方相关代码:
ExternalDataExchangeService dataService;
dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
BugFlowService bugFlow = new BugFlowService();
dataService.AddService(bugFlow);
WorkflowInstance instance = workflowRuntime.CreateWorkflow(
<span class="kwrd">typeof</span>(wf_test1.chapter3_sequential));
instance.Start();
Bug bug = <span class="kwrd">new</span> Bug(1, <span class="str">"Bug Title"</span>, <span class="str">"Bug Description"</span>);
bugFlow.CreateBug(instance.InstanceId, bug);</pre>
注意事项说明:
1、接口必须打上ExternalDataExchange标签,才能使用工作流的数据交换服务[DataExchangeService]。
2、事件中参数类型必须继承自ExternalDataEventArgs类,参数类型必须打上Serializable标签。
3、事件句柄建议使用EventHandler<T>的方式,否则可能收到“The event BugAdded has to be of type EventHandler where T derives from ExternalDataEventArgs”的错误提示。
4、需要引用System.Workflow.Activities命名空间。