给大家分享一下,如何完全使用代码自定义的创建生成工作流文件(用代码创建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 = ; 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="">
<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;</mca:CSharpValue>
</InArgument>
</If.Condition>
</If>
</Sequence>

流程控制

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

  1. C#动态生成图书信息XML文件

    通过C#动态生成图书信息XML文件,下面有个不错的示例,需要的朋友可以参考下 通过C#动态生成图书信息XML文件(Books.xml),文件如下: 复制代码代码如下: <?xml version ...

  2. log4j2 不使用配置文件,动态生成logger对象

    大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,比如log4j.xml,里面配置好Appenders和Loggers,但是前一阵想做某需求的时候,想要的效果是每一个任 ...

  3. MSChart使用之动态生成多个多行ChartArea

    前台代码: <asp:Chart ID=" > <Titles> <asp:Title Name="Title1" runat=" ...

  4. Python调用ansible API系列(四)动态生成hosts文件

    方法一:通过最原始的操作文件的方式 #!/usr/bin/env python # -*- coding: utf-8 -*- """ 通过操作文件形式动态生成ansib ...

  5. cglib根据数据动态生成对象

    最近有个任务:根据查询SQL直接导出报表 实现关键是,怎么根据sql查询的数据动态生成对象列表,想到Cglib动态代理实现 废话少说,上代码: 定义动态生成Java Bean类: import jav ...

  6. java 动态生成SQL

    代码如下: /** * 动态生成SQ及SQL参数L * @param ve 接收到的消息的CHGLIST * @param paramList MQ消息中的SQL参数 * @param t 泛型对象 ...

  7. Log4j2 - 动态生成Appender

    功能需求 项目里将User分成了各个区域(domain),这些domain有个标志domainId,现在要求在打印日志的时候,不仅将所有User的日志都打印到日志文件logs/CNTCore.log中 ...

  8. jquery给动态生成的元素绑定事件,on函数

    首先先解释一下什么是动态生成的元素:动态生成的元素即我们用jquery的内部插入函数append()所生成的html代码.相对的也有静态生成的元素:即直接编写在页面的html代码. 下面通过例子来讲解 ...

  9. C#动态生成XML

    通过C#动态生成图书信息XML文件(Books.xml),文件如下: <?xml version="1.0" encoding="iso-8859-1"? ...

随机推荐

  1. Django通用视图执行过程

    使用通用视图后,Django请求处理过程(以ListView为例):在我们自定义的视图中: class IndexView(ListView): template_name = 'blog/index ...

  2. CCS内存数据转成图片

    在嵌入式DSP图像处理开发过程中,经常需要将DSP内存中的图像数据保存下来,作为数据集.CCS5.4或者CCS3.3都只支持保存内存原始数据而不支持将内存数据直接存储为一张图片,为了能将CCS保存的. ...

  3. (解决方法)Android studio 运行时报错Do you want to uninstall the existing application?的解决方法

    在Android studio中,有时运行会报错: WARNING: Uninstalling will remove the application data!Do you want to unin ...

  4. zookeeper + dubbo + spring boot

    最近开始接触了分布式的一些东西,这里给自己作一个学习笔记. 这里只是做一个运行demo,具体的理论知识就不在这里阐述了. 1.zookeeper的安装与启动 下载地址:http://www.apach ...

  5. NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)

    因工作需要用到跨合并单元格获取数据,所以写了个NPOI扩展类. 主要方法如下: 1.判断指定行/列索引(单元格)是否为合并单元格. 2.获取指定列索引的实际含有数据的单元格. 3.返回指定行/列索引的 ...

  6. Linux之yum

    yum相当于是linux的本地的软件资源库,每个一段时间必须手动更新yum update

  7. Diary of Codeforces Round #402 (Div. 2)

    这一场的表现可以用"全程智障"4个字,生动传神地描述出来. About 写题: A. 写了一堆if比较大小, 这很勤勉.(绝对值君对自己の存在感为0表示很难过.) B. 题,直接读 ...

  8. [深入学习Redis]RedisAPI的原子性分析

    在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...

  9. 老李推荐:第1章2节《MonkeyRunner源码剖析》概述:边界

    老李推荐:第1章2节<MonkeyRunner源码剖析>概述:边界   边界 怎么样才算分析清楚一个事物的原理是什么呢?就以前面提到的<LINUX内核源代码情景分析>为例子,分 ...

  10. Java集合总结系列2:Collection接口

    Collection 接口是 Java 集合类的一个根接口,Java 在 Collection 接口中定义了许多通用的数据操作类方法以及判断类方法. 通过查看 API 文档或源码的方式,我们可以了解到 ...