zoukankan      html  css  js  c++  java
  • 工作流系统中的语法标记系统

    以微软的WF为基础,为达到ERP中的批核与通知目的,参考现有系统中的技术,在此分享其中的技巧。

    先来看最终的结果,也就是下图中的工作流宿主。

    image

    在上面的工作流定义中,除工作流宿主(rehost)技术外,还需要解决规则表达式的解析难题。

    .NET WF提供的规则编辑器是基于代码的,但对于一个无代码的开发环境,需要找到一种表达式的设计,解析规范。

    比如,在运行时,我们需要根据当前的运行参数解析出以上表达式的分支,最终流向哪个批核结点。

    经过摸索,我提供现有系统中已经应用的三种方案,供读者参考。

    1 查询表达式

    比如一个费用报销流程,当报销金额小于1000元时,可由部门主管直接批核。用SQL语句表达如下:

    SELECT AMOUNT  FROM dbo.ICMOVH WHERE AMOUNT <1000  
    
    AND REF_NO='<%InventoryMovementEntity.RefNo%>‘
     
    <% 标记表示当前正在运行的业务对象,<%InventoryMovementEntity.RefNo%> 这一句可取到当前业务对象的标识值。再与金额条件Amount(小于等于1000)组合,当存在这样的单据时,即为满足分支条件,由部门主管批核。
     

    2 查询语句

    查询语句的作用是为了发送消息通知,将SQL命令通过参数化的方式封装,达到运行时获取数据的目的。
    比如一个安全库存报警,当物料安全库存变动时,物料的库存余额小于当前物料设定的安全库存。
    image 
    为了查询数据,设计出一种新语法标记,例子如下:
    <%RepeatEachRecord_Begin.SqlQuery1%> 
    
    Job No: <%SqlQuery1.job_no%>
    
    <%RepeatEachRecord_End.SqlQuery1%>

    通过上图的界面设计中可看出,一个消息通知可包含很多个SQL命名查询,每个SQL命名查询可返回一个或多个数据行,我们在消息文本中用特定的语法,解析出命名查询中字段,即可达到获取数据的目的。

    3 常量

    工作流中的活动可理解为一个封装的独立的代码片段,为了与外界通信,必须向活动传递参数。有时候参数是固定的值,比如当前的报销单据,在前面我们用到过<%InventoryMovementEntity.RefNo%>表示报销单据编号。

    若是要取到当前登录系统的用户,可用<%SessionEntity.UserId%>来获取。

    比如给仓库单据增加一个验证,取出当前用户创建的引用(Reference)为空的参考编号。可通过下面的SQL语句实现:

    SELECT RefNo  FROM dbo.ICMOVH WHERE REFERENCE IS NULL 
    
    AND CREATED_BY='<%SessionEntity.UserId%>‘
     

    4 调用程序代码

    在一套业务工作流系统中调用代码实在是无奈之举。如果发生的业务很有规律,可考虑封装为活动以方便重用。

    代码活动的表达方式如下:

    image

    我用了三行标记为的是表示一个.NET方法:
    assembly=Microsoft.Workflow
    
    class=Microsoft.Workflow.Extension
    
    method=Microsoft.Workflow.Extension.VoucherPost
    如果你熟悉.NET反射,很快能写出调用这个方法的代码。
    Assembly assembly = null;
    
    Type type = null;
    
    string method = string.Empty;
    
    List<string> format = new List<string>() { "assembly", "class", "method" };
    
    string[] codes = Regex.Split(this.Code, ";");
    
    foreach (string code in codes)
    
    {
    
       if (string.IsNullOrWhiteSpace(code))
    
                        continue;
    
       string[] segments = Regex.Split(code, "=");
    
       if (Microsoft.Common.Shared.StringCompare(segments[0].ToUpper(), "assembly".ToUpper()) == 0)
    
             assembly = Assembly.Load(segments[1]);
    
       if (Microsoft.Common.Shared.StringCompare(segments[0].ToUpper(), "class".ToUpper()) == 0)
    
             type = assembly.GetType(segments[1]);
    
       if (Microsoft.Common.Shared.StringCompare(segments[0].ToUpper(), "method".ToUpper()) == 0)
    
            method = segments[1];
    
    }
    
    type.GetMethod(method, BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
    从最后一段代码中可以看出,上面标记的方法必须是静态(static,非实例)方法。
     
    最后,我将前三种情况附加到程序中,以帮助对话框的形式提供给工作流开发人员。
    image 
     
    我这里所提到的工作流是以微软的WF为基础开发的一套工作流系统,如果你需要自定义一套工作流设计,业务开发,表达式解析等功能,文中的标记技术可供您参考。
     
  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/5476030.html
Copyright © 2011-2022 走看看