其实和工作流的交互我前面已经有个文字了。就是这个:给WWF传递参数
这个文章主要说的就是第二中情况。事件和方法,是指工作流添加activity的事件来接受和传递参数
。这里面有两个很重要的活动CallExternalMethodActivity 和HandleExternalEvent 。
前者是调用方法,后者是调用事件。其中宿主应用程序调用事件,工作流调用方法。这个两个是基本的概念。
事件只有两个参数,一个是sender谁触发的,一个是相关的参数。这是固定。
先说这些基本概念,然后说一个具体例子。这个例子运行一个工作流,然后先开始投票这个工作。然后要给一个人投票,支持或者反对这是两个事件。
&<60;&<60;&<60; 新建顺序工作流控制台项目。添加window.form引用。打开program文件,里面已经有了代码。使用这个代码当然也可以。也可以使用这个代码,和原来的代码基本相同,就是添加了。工作流引擎创建和结束的事件输出而已
class Program
{
static AutoResetEvent waitHandle = new AutoResetEvent(false);
static VotingService votingService;
static void Main(string[] args)
{
WorkflowRuntime workflowRuntime = new WorkflowRuntime();
ExternalDataExchangeService dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
votingService = new VotingService();
dataService.AddService(votingService);
workflowRuntime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowCreated);
workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
Type type = typeof(Workflow1);
workflowRuntime.CreateWorkflow(type).Start();
waitHandle.WaitOne();
Console.WriteLine("Press any key to exit...");
Console.Read();
}
static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("Workflow " + e.WorkflowInstance.InstanceId.ToString() + " completed.");
waitHandle.Set();
}
static void workflowRuntime_WorkflowCreated(object sender, WorkflowEventArgs e)
{
Console.WriteLine("Workflow " + e.WorkflowInstance.InstanceId.ToString() + " created.");
}
}
ExternalDataExchangeService dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
votingService = new VotingService();
dataService.AddService(votingService);
注意这段话,使用交互必须添加这个服务,VotingService就是将要使用的服务类。
这里要说明的服务类的格式是基本固定。一个接口。接口中定义事件和方法,一个参数类继承ExternalDataEventArgs而且要实现序列化,然后就是实现类他继承接口。
类文件如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Activities;
using System.Windows.Forms;
using System.Threading;
using System.Workflow.Runtime;
namespace Communition2_25
{
[Serializable]
public class VotingEventArgs : ExternalDataEventArgs//参数类
{
private string alias;
public VotingEventArgs(Guid InstanceID, string alias)
: base(InstanceID)
{
this.alias = alias;
}
public string Alias
{
get { return this.alias; }
set { this.alias = value; }
}
}
[ExternalDataExchange]
internal interface IVotingService//接口定义事件和方法。宿主触发事件,工作流使用方法
{
event EventHandler<VotingEventArgs> ApproveProposal;
event EventHandler<VotingEventArgs> RejectProposal;
void CreateBallot(string alias);
}
internalclass VotingService : IVotingService
{
public event EventHandler<VotingEventArgs> ApproveProposal;
public event EventHandler<VotingEventArgs> RejectProposal;
public void CreateBallot(string alias)//
{
Console.WriteLine("Ballot created for " + alias + ".");
ThreadPool.QueueUserWorkItem(ShowVotingDialog, new VotingEventArgs(WorkflowEnvironment.WorkflowInstanceId, alias));
}
public void ShowVotingDialog(object o)
{
DialogResult result;
VotingEventArgs votingEventArgs = o as VotingEventArgs;
Guid instanceId = votingEventArgs.InstanceId;
string alias = votingEventArgs.Alias;
result = MessageBox.Show("Approve Proposal, " + alias + "?", alias + " Ballot", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
if (ApproveProposal != null)
ApproveProposal(null, votingEventArgs);
}
else
{
if (RejectProposal != null)
RejectProposal(null, votingEventArgs);
}
}
}
}
然后打开workflow文件的设计视图:添加CallExternalMethodActivity .设置他的几个必须属性
接口和方法,打开选择框可以看到我们已经定义好的接口IVotingService,然后选择方法CreateBallot。这是这个方法有个参数alias在面板中设置Jim。这个活动就设置完毕了。
然后我们添加一个listen活动。这个listen活动是有两个以上的事件活动组成的。他的特点是只要其中一个事件执行那么整个listen就算完成了。
我们托两个HandleExternalEvent分别放到左支和右支。左侧那个改名字Approve右侧改名Reject表示一个引发支持事件一个引发反对事件。点击Arrpove活动设置他的属性其中接口和事件名称是必须。选择IVotingService接口,和ApproveProposal事件。Reject活动同样处理只是他引发RejectProposal事件。此外还有设置当这个事件引发后调用什么方法,点击approve活动其中有个属性Invoked设置OnApproved。我们在后台文件中 添加这个方法就行了。
private void OnApproved(object sender, ExternalDataEventArgs e)
{
Console.WriteLine("Proposal Approved :" + votingArgs.Alias);
}
Reject活动相同设置
private void OnRejected(object sender, ExternalDataEventArgs e)
{
Console.WriteLine("Proposal Rejected : " + votingArgs.Alias);
}
这个地方有个要说明的地方。点击事件活动的时候下面有两个参数一个e和一个sender。他们提供了把e参数,就是我们事件中定义的e这个参数绑定给一个字段或属性的功能。我们选择绑定给一个新的成员,然后选择属性输入名称votingArgs,最后点击确定,这样工作流文件中多了这样一个属性
public static DependencyProperty votingArgsProperty = DependencyProperty.Register("votingArgs", typeof(Communition2_25.VotingEventArgs), typeof(Communition2_25.Workflow1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Parameters")]
public VotingEventArgs votingArgs
{
get
{
return ((Communition2_25.VotingEventArgs)(base.GetValue(Communition2_25.Workflow1.votingArgsProperty)));
}
set
{
base.SetValue(Communition2_25.Workflow1.votingArgsProperty, value);
}
}
这样我们在触发支持事件后的OnApproved方法中就可以得到事件参数。就是alias。
private void OnApproved(object sender, ExternalDataEventArgs e)
Console.WriteLine("Proposal Approved :" + votingArgs.Alias);
}
这样这个工作流就完成了。
编译运行就ok
这个文章主要说的就是第二中情况。事件和方法,是指工作流添加activity的事件来接受和传递参数
。这里面有两个很重要的活动CallExternalMethodActivity 和HandleExternalEvent 。
前者是调用方法,后者是调用事件。其中宿主应用程序调用事件,工作流调用方法。这个两个是基本的概念。
事件只有两个参数,一个是sender谁触发的,一个是相关的参数。这是固定。
先说这些基本概念,然后说一个具体例子。这个例子运行一个工作流,然后先开始投票这个工作。然后要给一个人投票,支持或者反对这是两个事件。
&<60;&<60;&<60; 新建顺序工作流控制台项目。添加window.form引用。打开program文件,里面已经有了代码。使用这个代码当然也可以。也可以使用这个代码,和原来的代码基本相同,就是添加了。工作流引擎创建和结束的事件输出而已
class Program
{
static AutoResetEvent waitHandle = new AutoResetEvent(false);
static VotingService votingService;
static void Main(string[] args)
{
WorkflowRuntime workflowRuntime = new WorkflowRuntime();
ExternalDataExchangeService dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
votingService = new VotingService();
dataService.AddService(votingService);
workflowRuntime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowCreated);
workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
Type type = typeof(Workflow1);
workflowRuntime.CreateWorkflow(type).Start();
waitHandle.WaitOne();
Console.WriteLine("Press any key to exit...");
Console.Read();
}
static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("Workflow " + e.WorkflowInstance.InstanceId.ToString() + " completed.");
waitHandle.Set();
}
static void workflowRuntime_WorkflowCreated(object sender, WorkflowEventArgs e)
{
Console.WriteLine("Workflow " + e.WorkflowInstance.InstanceId.ToString() + " created.");
}
}
ExternalDataExchangeService dataService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataService);
votingService = new VotingService();
dataService.AddService(votingService);
注意这段话,使用交互必须添加这个服务,VotingService就是将要使用的服务类。
这里要说明的服务类的格式是基本固定。一个接口。接口中定义事件和方法,一个参数类继承ExternalDataEventArgs而且要实现序列化,然后就是实现类他继承接口。
类文件如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Activities;
using System.Windows.Forms;
using System.Threading;
using System.Workflow.Runtime;
namespace Communition2_25
{
[Serializable]
public class VotingEventArgs : ExternalDataEventArgs//参数类
{
private string alias;
public VotingEventArgs(Guid InstanceID, string alias)
: base(InstanceID)
{
this.alias = alias;
}
public string Alias
{
get { return this.alias; }
set { this.alias = value; }
}
}
[ExternalDataExchange]
internal interface IVotingService//接口定义事件和方法。宿主触发事件,工作流使用方法
{
event EventHandler<VotingEventArgs> ApproveProposal;
event EventHandler<VotingEventArgs> RejectProposal;
void CreateBallot(string alias);
}
internalclass VotingService : IVotingService
{
public event EventHandler<VotingEventArgs> ApproveProposal;
public event EventHandler<VotingEventArgs> RejectProposal;
public void CreateBallot(string alias)//
{
Console.WriteLine("Ballot created for " + alias + ".");
ThreadPool.QueueUserWorkItem(ShowVotingDialog, new VotingEventArgs(WorkflowEnvironment.WorkflowInstanceId, alias));
}
public void ShowVotingDialog(object o)
{
DialogResult result;
VotingEventArgs votingEventArgs = o as VotingEventArgs;
Guid instanceId = votingEventArgs.InstanceId;
string alias = votingEventArgs.Alias;
result = MessageBox.Show("Approve Proposal, " + alias + "?", alias + " Ballot", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
if (ApproveProposal != null)
ApproveProposal(null, votingEventArgs);
}
else
{
if (RejectProposal != null)
RejectProposal(null, votingEventArgs);
}
}
}
}
然后打开workflow文件的设计视图:添加CallExternalMethodActivity .设置他的几个必须属性
接口和方法,打开选择框可以看到我们已经定义好的接口IVotingService,然后选择方法CreateBallot。这是这个方法有个参数alias在面板中设置Jim。这个活动就设置完毕了。
然后我们添加一个listen活动。这个listen活动是有两个以上的事件活动组成的。他的特点是只要其中一个事件执行那么整个listen就算完成了。
我们托两个HandleExternalEvent分别放到左支和右支。左侧那个改名字Approve右侧改名Reject表示一个引发支持事件一个引发反对事件。点击Arrpove活动设置他的属性其中接口和事件名称是必须。选择IVotingService接口,和ApproveProposal事件。Reject活动同样处理只是他引发RejectProposal事件。此外还有设置当这个事件引发后调用什么方法,点击approve活动其中有个属性Invoked设置OnApproved。我们在后台文件中 添加这个方法就行了。
private void OnApproved(object sender, ExternalDataEventArgs e)
{
Console.WriteLine("Proposal Approved :" + votingArgs.Alias);
}
Reject活动相同设置
private void OnRejected(object sender, ExternalDataEventArgs e)
{
Console.WriteLine("Proposal Rejected : " + votingArgs.Alias);
}
这个地方有个要说明的地方。点击事件活动的时候下面有两个参数一个e和一个sender。他们提供了把e参数,就是我们事件中定义的e这个参数绑定给一个字段或属性的功能。我们选择绑定给一个新的成员,然后选择属性输入名称votingArgs,最后点击确定,这样工作流文件中多了这样一个属性
public static DependencyProperty votingArgsProperty = DependencyProperty.Register("votingArgs", typeof(Communition2_25.VotingEventArgs), typeof(Communition2_25.Workflow1));
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[BrowsableAttribute(true)]
[CategoryAttribute("Parameters")]
public VotingEventArgs votingArgs
{
get
{
return ((Communition2_25.VotingEventArgs)(base.GetValue(Communition2_25.Workflow1.votingArgsProperty)));
}
set
{
base.SetValue(Communition2_25.Workflow1.votingArgsProperty, value);
}
}
这样我们在触发支持事件后的OnApproved方法中就可以得到事件参数。就是alias。
private void OnApproved(object sender, ExternalDataEventArgs e)
Console.WriteLine("Proposal Approved :" + votingArgs.Alias);
}
这样这个工作流就完成了。
编译运行就ok
本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。