WF4.0以上使用代码完整自定义动态生成执行工作流Xaml文件


给大家分享一下,如何完全使用代码自定义的创建生成工作流文件(用代码创建Xaml文件),并且动态加载运行所生成的工作流。

工作流生成后 在Xaml文件里的主要节点如下:

输入输出参数

  <x:Members>
    <x:Property Name="Item" Type="InArgument(qm:RuleModel)" />
    <x:Property Name="Result" Type="OutArgument(x:Int32)" />
  </x:Members>

我们先创建工作流中使用的 输入、输出参数,主要是为了我们想自定数据或提供一些辅助方法到工作流中,

items:为自定义节点数据,主要是用来生成流程的数据(此数据为自己定义类的数据实体)

        public  ActivityBuilder CreateRule(string name,params RuleCondtionNode[] items)
        {
            var item = CreateProperty("Item",true); //生成输入参数
            var Reulst = CreateProperty("Result",false);//生成输出参娄
            ActivityBuilder wf = new ActivityBuilder();
            wf.Name = name;
            wf.Properties.Add(item);//把参数加入到创建的工作流中
            wf.Properties.Add(Reulst);
            wf.Implementation = CreateNodes(items);//开始用自定义的数据 创建流程节点
            return wf;
        }

创建输入、输出参数: RuleModel:为我自定义要传入到工作流中使用的实体

        public  DynamicActivityProperty CreateProperty(string name,bool inOut)
        {
            var item = new DynamicActivityProperty();
            item.Name = name;
            item.Type = inOut? typeof(InArgument<RuleModel>): typeof(OutArgument<int>);//输入 OR 输出 是根据typeof 里的类型来决定的
            return item;
        }

创建流程节点:

   public Activity CreateNodes(params RuleCondtionNode[] model)
        {
            Sequence item = new Sequence();
            for (int i = 0; i < model.Length; i++)
            {
                item.Activities.Add(CreateNodeForType(model[i]));//把创建好的流程分去加入到活动中
            }
            return item;
        }

        public InArgument<bool> CreateIf(string codeStr)
        {
            return new CSharpValue<bool>(codeStr); //创建返回结果为 bool类型的表达式 这里采用的是用C#代码 主要为 IF 提示条件使用 
        }

        public Assign<T> CreateAssign<T>(string name,string codeStr)
        {
            var item = new Assign<T>(); //这里创建的是 工作流中的 赋值操作 A=B
            item.To = new ArgumentReference<T>(name); // A
            item.Value = new CSharpValue<T>(codeStr); //B:这是创建的是 C#代码表达式 Value是一个 InArgument<T> 类型 所以其它类型也行 我只是为了灵活采用C#代码
            return item;
        }

通过上面几步可实现一个简单的工作流了,完整的代码这里并没有,但是关键性的代码都在。

下面到了生成 Xaml 字符串的环节:

 private static readonly string[] rfitem = new string[] { //这里是我们需要在Xaml中生成的命名空间 很重要 我们想住工作流中添加任务扩展类靠它了
            "System",
            "System.Collections.Generic",
            "System.Linq",
            "System.Text",
            "QDRuleEngine.Model" //这是我自定义的类型
            };
        static RuleCreateHelper()
        {
            refList = rfitem.Select(c => new AssemblyReference() { AssemblyName = new System.Reflection.AssemblyName(c) }).ToList();//把命名空间的程序集加上
        }
        private static List<AssemblyReference> refList = new List<AssemblyReference>();//这里是Xaml中生成的 引用程序集 没有程序集大家懂的。生成好了也用不了


 public  string BuilderString(ActivityBuilder item)
        {
            TextExpression.SetNamespacesForImplementation(item, rfitem);//生成命名空间
            TextExpression.SetReferencesForImplementation(item, refList);//生成引用程序集
            StringBuilder sb = new StringBuilder();
            StringWriter tw = new StringWriter(sb);
            System.Xaml.XamlWriter xw = ActivityXamlServices.CreateBuilderWriter(new XamlXmlWriter(tw, new XamlSchemaContext()));//交给它来生成Xaml
            var xor = new XamlObjectReaderSettings();

            try
            {
                XamlObjectReader reader = new XamlObjectReader(item, xor);
                XamlServices.Transform(reader, xw);//通过此步我们就可以得到我们想要的 Xaml 字符串了
            }
            catch (Exception ex)
            {

            }

            return sb.ToString();//得到生成好的 Xaml 字符串  拿到这个字符串就可以 保存成Xaml工作流文件了
        }

命名空间引用:

  <TextExpression.NamespacesForImplementation>
    <sco:Collection x:TypeArguments="x:String">
      <x:String>System</x:String>
      <x:String>System.Collections.Generic</x:String>
      <x:String>System.Linq</x:String>
      <x:String>System.Text</x:String>
      <x:String>QDRuleEngine.Model</x:String>
    </sco:Collection>
  </TextExpression.NamespacesForImplementation>

引用程序集:

  <TextExpression.ReferencesForImplementation>
    <scg:List x:TypeArguments="AssemblyReference" Capacity="8">
      <AssemblyReference>System</AssemblyReference>
      <AssemblyReference>System.Collections.Generic</AssemblyReference>
      <AssemblyReference>System.Linq</AssemblyReference>
      <AssemblyReference>System.Text</AssemblyReference>
      <AssemblyReference>QDRuleEngine.Model</AssemblyReference>
    </scg:List>
  </TextExpression.ReferencesForImplementation>

我们生成好了想要的工作流后就是动态加载执行了:

       public  Activity LoadRule(string xmlStr)
        {
            Activity item = null;
            try
            {
                item = ActivityXamlServices.Load(new StringReader(xmlStr),//拿到我们生成好的Xaml字符串 转换成工作流
                new ActivityXamlServicesSettings()
                {
                    CompileExpressions = true  //如果在生成时采用了C#代码作为表达式时,必需把此值设为True 否则报错
                });
            }
            catch (Exception ex)
            {
                item = null;
            }

            return item;
        }


WorkflowInvoker item = new WorkflowInvoker(rule);//

 RuleModel model = new RuleModel(info, null, null, null, condition, new List<RuleRunLogInfo>());
//这是我们自定义的实体 刚才为此实体加了 命名空间 和 程序集 此实体我们可在工作流中的C#表达式中使用 例:A.MyFunc(123) 表达式为字符串 注意双引号
var result = item.Invoke(new Dictionary<string, object>()//传入我们需要的参数 执行工作流 如果 传入了工作流中没有定义的参数 会报错 { ["Item"] = model });
Console.Write(result["Result"]); //得到执行入返回的结果

完整的工作流生成示例代码 http://pan.baidu.com/s/1gfl9ZpD

流程控制:

  <Sequence>
    <If>
      <If.Condition>
        <InArgument x:TypeArguments="x:Boolean">
          <mca:CSharpValue x:TypeArguments="x:Boolean">Item.Condition.GetValue&lt;Int32&gt;("sql_2017010306288856")&gt;0</mca:CSharpValue>
        </InArgument>
      </If.Condition>
    </If>
  </Sequence>
流程控制

优质内容筛选与推荐>>
1、简述一致性哈希算法
2、解决js服务器缓存
3、rbac基于角色的权限管理系统(java:spring mvc + mybatis + druid + redis)
4、Nginx 源码分析-- 模块module 解析执行 nginx.conf 配置文件流程分析 二
5、矩阵, 矩阵 , Android基础控件之ImageView


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn