平庸与杰出=加法与减法

思考其乐无穷 IT剩者为王

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
在WF状态机的State活动中,都是从事件活动开始,通过callExternalMethod活动调用方法来执行需要执行的业务.

在工作流创建时候,我们可以通过参数的方式将工作流需要的共有数据传递给工作流,这样工作流可以任何时候访问这些数据(通过工作流属性实现了数据的get和set)。
工作流的CreateWorkflow方法:
public WorkflowInstance CreateWorkflow (Type workflowType,Dictionary<string, Object> namedArgumentValues)
参数namedArgumentValues就是我们需要的参数,可以这样组装namedArgumentValues参数:
 Dictionary<string, object> namedArgumentValues= new Dictionary<string, object>();=           
           
namedArgumentValues.Add("UserId", userId);
           
namedArgumentValues.Add("Xml", xml);          
           
namedArgumentValues.Add("OrderId", orderId);

通过传参的方式只能在工作流创建的时候将数据写入,在工作流重新被load后,没有办法给工作流实例(WorkflowInstance)添加参数或者写入数据。
但是在实际业务中每个业务操作都可能需要传入一些数据,比如订单审批人,审批金额等,这样就出现了我在开发中遇到的问题,如何给工作流实例传递值?

大概的解决思路在
关于wf中传参的问题:如何在workflow实例钝化后重新load时传参! 做了说明。

第一步:创建自定义事件类,比如OrderDataEventArgs,创建自定义事件类的时候需要注意两点:首先要继承ExternalDataEventArgs,另外就是要添加序列化声明
[Serializable]
    
public class OrderDataEventArgs : ExternalDataEventArgs
    {
        
private string corpIdValue;
        
private string userIdValue;
        
private int stampDateValue;
        
private string orderIdValue;
        
private string xmlValue;

        
public OrderDataEventArgs(Guid instanceId, string corpId, string userId, int stampDate)
            : 
base(instanceId)
        {
            orderIdValue 
= instanceId.ToString();
            corpIdValue 
= corpId;
            userIdValue 
= userId;
            stampDateValue 
= stampDate;
            
//xmlValue = xml;

            WaitForIdle 
= true;
        }

        
public OrderDataEventArgs(Guid instanceId, string corpId, string userId, string xml)
            : 
base(instanceId)
        {
            orderIdValue 
= instanceId.ToString();
            corpIdValue 
= corpId;
            userIdValue 
= userId;
            xmlValue 
= xml;

            WaitForIdle 
= true;
        }

        
public string OrderId
        {
            
get { return orderIdValue; }
            
set { orderIdValue = value; }
        }

        
public string CorpId
        {

            
get { return corpIdValue; }
            
set { corpIdValue = value; }
        }

        
public string UserId
        {
            
get { return userIdValue; }
            
set { userIdValue = value; }
        }

        
public int StampDate
        {
            
get { return stampDateValue; }
            
set { stampDateValue = value; }
        }

        
public string Xml
        {
            
get { return xmlValue; }
            
set { xmlValue = value; }
        }
    }

第二步:在状态机中添加OrderDataEventArgs类型的属性:
 public static DependencyProperty OrderEventArgsProperty = DependencyProperty.Register("OrderEventArgs"typeof(OrderDataEventArgs), typeof(Workflow1));

        [DescriptionAttribute(
"OrderEventArgs")]
        [CategoryAttribute(
"OrderEventArgs Category")]
        [BrowsableAttribute(
true)]
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        
public OrderDataEventArgs OrderEventArgs
        {
            
get
            {
                
return ((OrderDataEventArgs)(base.GetValue(Workflow1.OrderEventArgsProperty)));
            }
            
set
            {
                
base.SetValue(Workflow1.OrderEventArgsProperty, value);
            }
        }
然后将HandleExternalEventActivity活动事件e参数绑定到上面定义的OrderDataEventArgs属性,这样就能通过事件将需要的数据传递给工作流
设置过程图片:

e参数绑定到OrderDataEventArgs属性的代码如下,这是通过属性设置生成的代码:
 // 
            
// handleExternalEventActivity1
            
// 
            this.handleExternalEventActivity1.EventName = "Create";
            
this.handleExternalEventActivity1.InterfaceType = typeof(WorkflowInterface.IOrder);
            
this.handleExternalEventActivity1.Name = "handleExternalEventActivity1";
            activitybind1.Name 
= "Workflow1";
            activitybind1.Path 
= "OrderEventArgs";
            workflowparameterbinding1.ParameterName 
= "e";
            workflowparameterbinding1.SetBinding(System.Workflow.ComponentModel.WorkflowParameterBinding.ValueProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind1)));
            
this.handleExternalEventActivity1.ParameterBindings.Add(workflowparameterbinding1);
            
this.handleExternalEventActivity1.Invoked += new System.EventHandler<System.Workflow.Activities.ExternalDataEventArgs>(this.handleExternalEventActivity1_Invoked);
第三步:为callExternalMethodActivity活动的方法绑定参数,在IOrder接口中,SaveOrder方法需要两个参数:OrderId,UserId,这两个参数的值来自OrderEventArgsProperty 属性。
图片:

代码:
 // 
            
// callExternalMethodActivity1
            
// 
            this.callExternalMethodActivity1.InterfaceType = typeof(WorkflowInterface.IOrder);
            
this.callExternalMethodActivity1.MethodName = "SaveOrder";
            
this.callExternalMethodActivity1.Name = "callExternalMethodActivity1";
            activitybind1.Name 
= "Workflow1";
            activitybind1.Path 
= "OrderEventArgs.OrderId";
            workflowparameterbinding1.ParameterName 
= "orderId";
            workflowparameterbinding1.SetBinding(System.Workflow.ComponentModel.WorkflowParameterBinding.ValueProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind1)));
            activitybind2.Name 
= "Workflow1";
            activitybind2.Path 
= "OrderEventArgs.UserId";
            workflowparameterbinding2.ParameterName 
= "userId";
            workflowparameterbinding2.SetBinding(System.Workflow.ComponentModel.WorkflowParameterBinding.ValueProperty, ((System.Workflow.ComponentModel.ActivityBind)(activitybind2)));
            
this.callExternalMethodActivity1.ParameterBindings.Add(workflowparameterbinding1);
            
this.callExternalMethodActivity1.ParameterBindings.Add(workflowparameterbinding2);
OrderEventArgsProperty 属性数据传递的媒介,客户端组装OrderDataEventArgs,通过事件发送给工作流,工作流执行CallExternalMethodActivity的方法。
下面是关于工作流接口和实现的代码:
[ExternalDataExchange]
    
public interface IOrder
    {
        
/// <summary>
        
/// 创建订单
        
/// </summary>
        event EventHandler<OrderDataEventArgs> Create;

        
/// <summary>
        
/// 确认订单
        
/// </summary>
        event EventHandler<OrderDataEventArgs> Confirm;

        
/// <summary>
        
/// 完成
        
/// </summary>
        event EventHandler<OrderDataEventArgs> Complete;


        
void SaveOrder(string orderId, string userId);
        
     
    }

 [Serializable]
    
public class Order : IOrder
    {
        
public void RaiseCreateEvent(OrderDataEventArgs args)
        {
            
if (Create != null)
            {
                Create(
null, args);
            }
        }

        
public void RaisConfirmEvent(OrderDataEventArgs args)
        {
            
if (Confirm != null)
            {
                Confirm(
null, args);
            }
        }

        
public void RaisCompleteEvent(OrderDataEventArgs args)
        {
            
if (Complete != null)
            {
                Complete(
null, args);
            }
        }

        
#region IOrder Members

        
public event EventHandler<OrderDataEventArgs> Create;

        
public event EventHandler<OrderDataEventArgs> Confirm;

        
public event EventHandler<OrderDataEventArgs> Complete;       

        
public void SaveOrder(string orderId, string userId)
        {
            
// 得到通过OrderDataEventArgs传递的数据
            Console.WriteLine("OrderId value {0}, UserId value {1}", orderId, userId);
        }

        
#endregion
    }
最后一步:调用代码:
WorkflowHelper workflowHelper;
        Order OrderEx;
        
public Form1()
        {
            InitializeComponent();

            OrderEx 
= new Order();
            workflowHelper 
= new WorkflowHelper(OrderEx);
        }

        Guid InstanceId 
= new Guid("74E512AA-AC75-45a1-8818-0F77C8670AB4");
        
string userId = "F8E05185-3A4B-48c8-8C37-3B4EBD03B7AA";
        
string corpId = "b5d183ab-dc95-4fdd-a7ad-562822047ce6";

        
private void btnCreate_Click(object sender, EventArgs e)
        {
            workflowHelper.LoadWorkflow(InstanceId);          
            
            OrderDataEventArgs ea 
= new OrderDataEventArgs(InstanceId, corpId, userId, "");
            ea.WaitForIdle 
= true;
            
            OrderEx.RaiseCreateEvent(ea);
            workflowHelper.LoadWorkflow(InstanceId);
        }

        
private void btnConfirm_Click(object sender, EventArgs e)
        {
            
//InstanceId = new Guid(textBox1.Text);           
            workflowHelper.LoadWorkflow(InstanceId);

            OrderDataEventArgs ea 
= new OrderDataEventArgs(InstanceId, corpId, userId, 1);
            ea.WaitForIdle 
= true;
            OrderEx.RaisConfirmEvent(ea);
           
            workflowHelper.LoadWorkflow(InstanceId);   

        }

--畅所欲言,随心而谈--
本博客文章全部原创,转载请注明出处,谢谢
紫辰友创软件公司 http://www.bornsun.net/
版权所有 jiabao.cnblogs.com 转载请联系
posted on 2007-12-05 14:03 我是蚂蚁 阅读(1863) 评论(11)  编辑 收藏 所属分类: WF

评论

#1楼  2007-12-05 14:50 蓝色太平洋      
如果“创建订单”后将定单记录到数据库,是在那里写插入到数据库表的代码啊?在OrderDataEventArgs 里面吗
  回复  引用  查看    

#2楼 [楼主] 2007-12-05 15:10 我是蚂蚁      
--引用--------------------------------------------------
蓝色太平洋: 如果“创建订单”后将定单记录到数据库,是在那里写插入到数据库表的代码啊?在OrderDataEventArgs 里面吗
--------------------------------------------------------
在Iorder定义的方法中,比如
public void SaveOrder(string orderId, string userId)
{
// 得到通过OrderDataEventArgs传递的数据
Console.WriteLine("OrderId value {0}, UserId value {1}", orderId, userId);
}
一般是在callExternalMethodActivity活动中执行相关的方法
  回复  引用  查看    

#3楼  2007-12-05 15:44 蓝色太平洋      
谢谢你的回答,“创建定单”后:
public class Order : IOrder
{
public void RaiseCreateEvent(OrderDataEventArgs args)
{
if (Create != null)
{
Create(null, args);
。。。将定单写入数据库吗,
}
}

  回复  引用  查看    

#4楼 [楼主] 2007-12-05 15:50 我是蚂蚁      
@蓝色太平洋
RaiseCreateEvent是唤醒事件,通知workflow执行。

尽量不要在事件中做这个,而是在callExternalMethodActivity活动中
callExternalMethodActivity活动调用了SaveOrder方法,通过SaveOrder方法将订单写入。
  回复  引用  查看    

#5楼  2007-12-05 17:26 赤脚小子      
@楼主
你的callExternalMethodActivity活动调用SaveOrder如何将订单写入呢?
  回复  引用  查看    

#6楼 [楼主] 2007-12-05 17:32 我是蚂蚁      
--引用--------------------------------------------------
赤脚小子: @楼主
你的callExternalMethodActivity活动调用SaveOrder如何将订单写入呢?
--------------------------------------------------------
这是wf的基础啊,各个活动的应用场景。
建议看看那些基础的关于各个活动的介绍,如何使用各种活动,可以参考这篇:
http://www.cnblogs.com/jiabao/archive/2007/11/10/955424.html
  回复  引用  查看    

#7楼  2007-12-05 17:36 赤脚小子      
是啊,但是仔细看下,实际上所有对于callExternalMethodActivity的例子都是以Console为例的,纯粹为了演示。
我只是想看下楼主怎么实现这块的。
  回复  引用  查看    

#8楼  2007-12-05 18:03 Enzo      
呵呵 WF状态机
  回复  引用  查看    

#9楼 [楼主] 2007-12-06 19:43 我是蚂蚁      
--引用--------------------------------------------------
赤脚小子: 是啊,但是仔细看下,实际上所有对于callExternalMethodActivity的例子都是以Console为例的,纯粹为了演示。
我只是想看下楼主怎么实现这块的。
--------------------------------------------------------
既然能输出了,就能做其他的。这些教程性质的文章做到这个就可以了。
毕竟这个不是讲解数据库读写的
  回复  引用  查看    

#10楼  2007-12-07 17:04 蓝色太平洋      
我现在准备做下面的流程审批:中队的民警电脑坏了想申请维修,先填单,然后自动转到上一级领导审批,再转到技术科领导审批,同意后交技术科民警处理...;其实这个流程完全不用wf都可以完成,只是不是很明白用wf的好处在哪里?关于审批单及流程情况也一样要记录的数据库的啊?
  回复  引用  查看    

[DescriptionAttribute("OrderEventArgs")]
[CategoryAttribute("OrderEventArgs Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
可以简单介绍一下上面这些标记吗?我在网上及MSDN中也看了,但不是很理解.还有就是如何不通过SaveOrder(string orderId, string userId)来获得OrderDataEventArgs 中的数据呢?就是说,我想让流程实例在Idled状态的时候将实例连同OrderDataEventArgs中的数据一起保存到数据库中(不用callExternalMethodActivity保存OrderDataEventArgs中的数据),我在OnWorkflowIdled(object sender,WorkflowEventArgs e)中如何用e.WorkflowInstance来获取OrderEventArgsProperty属性有效OrderDataEventArgs数据呢??
  回复  引用    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-05 15:26 编辑过


相关链接: