本文是[我们为什么需要工作流]的姊妹篇,我使了类似的文风,
我们为什么需要WF
以前有人对我说,WF很难用,明明很简单的一个功能,用WF去做却那么繁琐,
有这种想法,那我觉得有两种可能,
一,你要实现的这个功能确实太简单
二,你把这个功能的实现过程想的太简单
先看一组列子这是一组非常简单的例子,分别是四个主题,分别代表程序发展的四个阶段
- 什么是程序
- 什么是具有控制流语句程序的控制流语句
- 什么是交互程序
- 什么是可视化交互程序
程序
程序是一连串指令的集合,
下面是一个技术算法的程序,
记得在89年的时候,我上小学5年级,那时我在PC1500上第一次用Basic写出了具有这个功能的程序.
那时候,每要做一次计算都要把程序再敲一遍,在我眼里,PC1500这个大家活还不如一个计算器
这是我那个Basic功能的C#版
class Program
{
static void Main(string[] args)
{
int x = 1; //加数
int y = 2; //被加数
int z = x + y; // 相加
System.Console.WriteLine(z); //在屏幕打印结果
}
}
具有控制流语句程序的控制流语句
控制流语句,
不久,我学会了一个很有意思的指今,他可以根据我设定的条件执行不同的代码,这时,我觉得PC1500这个大家活还有点意思.
这是我那个Basic功能的C#版
class Program
{
static void Main(string[] args)
{
string input = "123";
double temp ;
bool b=double.TryParse(input,out temp);
if (b)
{
System.Console.WriteLine("你输入的数字是:{0}",temp);
}
else
{
System.Console.WriteLine("你输入的不是数字");
}
}
}
交互程序
交互程序,有用户参与的,用户可以在程序的预设点控制程序的执行
初中三年,由于家人认为"玩"电脑是不务正业,会耽误学习,到了高中,胆大了,又开始"完"电脑了,这时用的是386,
我学会了一门新语言FoxBase,他很神奇,可以等我输入点什么以后再继续执行
这是我那个FoxBase功能的C#版
class Program
{
static void Main(string[] args)
{
while (true)
{
System.Console.WriteLine("要查看系统日期请按[y],按其它键退出程序");
string input = System.Console.ReadLine();
if (input == "y")
{
System.Console.WriteLine(DateTime.Now);
}
else
{
return;
}
}
}
}
可视化程序
可视化程序
到了大学,虽然我学的是文科,但我对编程的热情依然没改,一次,我无意中接处到了VB,这是一个让我疯狂的语言,他竟然可以写出Windows中的窗口.
这是我那个VB功能的C#版
//数据模型
public class myData
{
public int x;
public int y;
}
//数据操作
public static class myMaths
{
public static int add(myData data)
{
int z = data.x + data.y;
return z;
}
}
//展现1
public class windows1 : System.Windows.Forms.Form
{
System.Windows.Forms.Label title_label = new System.Windows.Forms.Label() { Text="请输入x"};
System.Windows.Forms.TextBox x_textBox = new System.Windows.Forms.TextBox() { Top = 30 };
System.Windows.Forms.Button ok_button = new System.Windows.Forms.Button() { Text = "确定",Top = 30, Left = 200};
public string x;
public windows1()
{
this.Controls.Add(title_label);
this.Controls.Add(x_textBox);
this.Controls.Add(ok_button);
ok_button.Click += new EventHandler(ok_button_Click);
}
void ok_button_Click(object sender, EventArgs e)
{
x = x_textBox.Text;
this.Hide();
}
}
//展现2
public class windows2 : System.Windows.Forms.Form
{
System.Windows.Forms.Label title_label = new System.Windows.Forms.Label() { Text = "请输入y" };
System.Windows.Forms.TextBox y_textBox = new System.Windows.Forms.TextBox() { Top = 30 };
System.Windows.Forms.Button ok_button = new System.Windows.Forms.Button() { Text = "确定", Top = 30, Left = 200 };
public string y;
public windows2()
{
this.Controls.Add(title_label);
this.Controls.Add(y_textBox);
this.Controls.Add(ok_button);
ok_button.Click += new EventHandler(ok_button_Click);
}
void ok_button_Click(object sender, EventArgs e)
{
y = y_textBox.Text;
this.Hide();
}
}
//展现3
public class windows3 : System.Windows.Forms.Form
{
System.Windows.Forms.Label title_label = new System.Windows.Forms.Label() { Text = "结果" };
System.Windows.Forms.TextBox z_textBox = new System.Windows.Forms.TextBox() { Top = 30 };
System.Windows.Forms.Button ok_button = new System.Windows.Forms.Button() { Text = "完成", Top = 30, Left = 200 };
public void showValue(string s)
{
this.z_textBox.Text = s;
}
public windows3()
{
this.Controls.Add(title_label);
this.Controls.Add(z_textBox);
this.Controls.Add(ok_button);
ok_button.Click += new EventHandler(ok_button_Click);
}
void ok_button_Click(object sender, EventArgs e)
{
this.Hide();
}
}
public class Program
{
static void Main(string[] args)
{
myControl();
}
static void myControl()
{
//初始化数据对象
myData data = new myData();
//-输入x
windows1 w1 = new windows1();
w1.ShowDialog();
//-输入y
windows2 w2 = new windows2();
w2.ShowDialog();
//-计算
data.y = int.Parse(w2.y);
data.x = int.Parse(w1.x);
int value;
value = myMaths.add(data);
//-显示结果
windows3 w3 = new windows3();
w3.showValue(z.ToString());
w3.ShowDialog();
}
}
第一步
第二步
第三步
面向流程开发基于配运行的程序
大学毕业后,干了一段时间律师,觉得无聊,于是决定改行做程序员
VB,VC,ASP,VB.NET,C#,一直没的再遇到一个让我激动的技术,
2005年时,我正在参考Shark用NET实现一个工作流平台,这时我接触了WF, 那时WF还没集成到NET中,是一个WinFX的组件,看到WF我就喜欢上这个家伙了.
后来我建议放弃Shark的思路,用WF做工作流平台.公司里所有人都反对,于是在WF与公司间,我选择了WF.
下面是一个用WF实现上面例子中的控制部分
[数据模型],[数据操作],[展现1],[展现2],[展现3],保持不变
先创建一组功能Avtivity
public partial class 初始化数据对象: Activity
{
public 初始化数据对象()
{
InitializeComponent();
}
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.Name = "初始化数据对象";
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
this.data = new myData();
return base.Execute(executionContext);
}
public static DependencyProperty dataProperty = DependencyProperty.Register("data", typeof(myData ), typeof(初始化数据对象));
[DescriptionAttribute("data")]
[CategoryAttribute("data Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public myData data
{
get
{
return ((myData )(base.GetValue(初始化数据对象.dataProperty)));
}
set
{
base.SetValue(初始化数据对象.dataProperty, value);
}
}
}
public partial class 输入x: Activity
{
public 输入x()
{
InitializeComponent();
}
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.Name = "输入x";
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
windows1 w1 = new windows1();
w1.ShowDialog();
this.data.x= int.Parse(w1.x);
return base.Execute(executionContext);
}
public static DependencyProperty dataProperty = DependencyProperty.Register("data", typeof(myData), typeof(输入x));
[DescriptionAttribute("data")]
[CategoryAttribute("data Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public myData data
{
get
{
return ((myData)(base.GetValue(输入x.dataProperty)));
}
set
{
base.SetValue(输入x.dataProperty, value);
}
}
}
public partial class 输入y: Activity
{
public 输入y()
{
InitializeComponent();
}
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.Name = "输入y";
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
windows2 w2 = new windows2();
w2.ShowDialog();
this.data.y = int.Parse(w2.y);
return base.Execute(executionContext);
}
public static DependencyProperty dataProperty = DependencyProperty.Register("data", typeof(myData), typeof(输入y));
[DescriptionAttribute("data")]
[CategoryAttribute("data Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public myData data
{
get
{
return ((myData)(base.GetValue(输入y.dataProperty)));
}
set
{
base.SetValue(输入y.dataProperty, value);
}
}
}
public partial class 计算: Activity
{
public 计算()
{
InitializeComponent();
}
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.Name = "计算";
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
value = myMaths.add(data);
return base.Execute(executionContext);
}
public static DependencyProperty valueProperty = DependencyProperty.Register("value", typeof(int), typeof(计算));
[DescriptionAttribute("value")]
[CategoryAttribute("value Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public int value
{
get
{
return ((int)(base.GetValue(计算.valueProperty)));
}
set
{
base.SetValue(计算.valueProperty, value);
}
}
public static DependencyProperty dataProperty = DependencyProperty.Register("data", typeof(myData), typeof(计算));
[DescriptionAttribute("data")]
[CategoryAttribute("data Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public myData data
{
get
{
return ((myData)(base.GetValue(计算.dataProperty)));
}
set
{
base.SetValue(计算.dataProperty, value);
}
}
}
public partial class 显示结果:Activity
{
public 显示结果()
{
InitializeComponent();
}
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.Name = "显示结果";
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
windows3 w3 = new windows3();
w3.showValue(value.ToString());
w3.ShowDialog();
return base.Execute(executionContext);
}
public static DependencyProperty valueProperty = DependencyProperty.Register("value", typeof(int), typeof(显示结果));
[DescriptionAttribute("value")]
[CategoryAttribute("value Category")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public int value
{
get
{
return ((int)(base.GetValue(显示结果.valueProperty)));
}
set
{
base.SetValue(显示结果.valueProperty, value);
}
}
}
创建控制流程
在WorkflowRuntime中创建实例,并运行实例
class Program
{
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(example5.myWorkflow));
instance.Start();
waitHandle.WaitOne();
}
}
}
为什么需要使用WF
下面,说一下为什么需要使用WF
说实话,我不是没见过世面,工作流的理轮,设计模式的理论我也学过一些
为什么需要使用WF,要实现流程控制我们也可用一些经典的设计模式去实现,比如下面的例子
职责链方式实现流程控制 引擎设计//引擎
public class wfEngine
{
//实例池
protected System.Collections.SortedList InstancePool;
public wfEngine()
{
InstancePool = new System.Collections.SortedList();
}
//添加实例到引擎
public string AddInstance(wfTemplet Instance)
{
InstancePool.Add(Instance.InstanceID, Instance.CurrentNode);
return Instance.InstanceID;
}
//工作流下移一结点
public bool ExecuteNextNode(string InstanceID)
{
if (InstancePool.Contains(InstanceID))
{
if (((wfNode)InstancePool[InstanceID]).NextNode != null)
{
InstancePool[InstanceID] = ((wfNode)InstancePool[InstanceID]).execute();
return true;
}
else
{
((wfNode)InstancePool[InstanceID]).execute();
InstancePool.Remove(InstanceID);
return false;
}
}
return false;
}
// 一次执行完实例的所有结点
public void AutoExecute(string InstanceID)
{
while (ExecuteNextNode(InstanceID))
{
AutoExecute(InstanceID);
}
}
//得到实例状态
public string getInstanceState(string InstanceID)
{
if (InstancePool.Contains(InstanceID))
{
return ((wfNode)InstancePool[InstanceID]).NodeId;
}
return null;
}
//得到引擎内的所有实例
public System.Collections.SortedList getInstances()
{
return this.InstancePool;
}
}
工作流模板
//工作流模板
public class wfTemplet
{
public string InstanceID;//实例ID
public wfTemplet(string InstanceID)
{
this.InstanceID = InstanceID;
}
public wfNode CurrentNode;
}
结点模板
//结点模板
public abstract class wfNode
{
public string InstanceId;//实例ID
public string NodeId;//结点ID
public wfNode(string InstanceID, string NodeId)
{
this.InstanceId = InstanceID;
this.NodeId = NodeId;
}
//下一结点
public wfNode NextNode;
//执行区
public abstract wfNode execute();
}
代码结点模板
//条件表达式类
public class conditionExpression
{
public object leftExpression;//左表达式
public object rightExpression;//右表达式
//比效方法
//可以跟据需要自定义左、右表达式,并重载比效运算符
public bool contrast()
{
if (leftExpression.Equals(rightExpression))
{ return true; }
else
{ return false; }
}
}
//条件结点模板类
public class conditionNode : wfNode
{
//构造函数
public conditionNode(string InstanceID, string NodeId)
: base(InstanceID, NodeId)
{ }
public conditionExpression expression;//表达式对象
public wfNode ElseNode;//否则结点
//执行区
public override wfNode execute()
{
if (expression.contrast())
{ return this.NextNode; }
else
{ return this.ElseNode; }
}
}
条件结点模板
//条件表达式类
public class conditionExpression
{
public object leftExpression;//左表达式
public object rightExpression;//右表达式
//比效方法
//可以跟据需要自定义左、右表达式,并重载比效运算符
public bool contrast()
{
if (leftExpression.Equals(rightExpression))
{ return true; }
else
{ return false; }
}
}
//条件结点模板类
public class conditionNode : wfNode
{
//构造函数
public conditionNode(string InstanceID, string NodeId)
: base(InstanceID, NodeId)
{ }
public conditionExpression expression;//表达式对象
public wfNode ElseNode;//否则结点
//执行区
public override wfNode execute()
{
if (expression.contrast())
{ return this.NextNode; }
else
{ return this.ElseNode; }
}
}
业务程流
public class 我的业务程流 : wfTemplet
{
public codeNode 结点A; //结点A:代码结点
public conditionNode 结点B; //结点B:条件结点
public codeNode 结点C; //结点C:代码结点
public codeNode 结点D; //结点D:代码结点
public codeNode 结点E; //结点E:代码结点
public 我的业务程流(string InstanceID)
: base(InstanceID)
{
/*
* 结点A
* |
* |
* 结点B
* (true)/ \(false)
* / \
* 结点C 结点D
* \ /
* \ /
* 结点E
*/
//结点A:代码结点
结点A = new codeNode(this.InstanceID, "结点A");
结点A.Code += new codeMethod(结点A_Code);
结点A.CodeParameter = "wxwinter的一个测试";
//结点B:条件结点
结点B = new conditionNode(this.InstanceID, "结点B");
//结点B的条件表达式
conditionExpression 条件表达式 = new conditionExpression();
结点B.expression = 条件表达式; //绑定条件表达式到结点B
//结点C:代码结点
结点C = new codeNode(this.InstanceID, "结点C");
结点C.Code += new codeMethod(结点C_Code);
结点C.CodeParameter = "结点C,条件的真结点";
//结点D:代码结点
结点D = new codeNode(this.InstanceID, "结点D");
结点D.Code += new codeMethod(结点D_Code);
结点D.CodeParameter = "结点D,条件的假结点";
//结点E:代码结点
结点E = new codeNode(this.InstanceID, "结点E");
结点E.Code += new codeMethod(结点E_Code);
结点E.CodeParameter = "完成";
//指定入口结点
this.CurrentNode = 结点A;
//设置结点关系
结点A.NextNode = 结点B;
结点B.NextNode = 结点C;
结点B.ElseNode = 结点D;
结点C.NextNode = 结点E;
结点D.NextNode = 结点E;
}
//结点A:代码
private void 结点A_Code(wfNode sender, object data)
{
Console.WriteLine("实例ID:" + sender.InstanceId + ":" + sender.NodeId + ":" + data.ToString());
}
//结点C:代码
private void 结点C_Code(wfNode sender, object data)
{
Console.WriteLine("实例ID:" + sender.InstanceId + ":" + sender.NodeId + ":" + data.ToString());
}
//结点B:代码
private void 结点D_Code(wfNode sender, object data)
{
Console.WriteLine("实例ID:" + sender.InstanceId + ":" + sender.NodeId + ":" + data.ToString());
}
//结点E:代码
private void 结点E_Code(wfNode sender, object data)
{
Console.WriteLine("实例ID:" + sender.InstanceId + ":" + sender.NodeId + ":" + data.ToString());
}
}
使用
class Program
{
static void Main()
{
wfEngine 引擎 = new wfEngine();
//实例03
我的业务程流 obj1 = new 我的业务程流("03");
obj1.结点B.expression.leftExpression = 100;
obj1.结点B.expression.rightExpression = 100;
//实例04
我的业务程流 obj2 = new 我的业务程流("04");
obj2.结点B.expression.leftExpression = 99;
obj2.结点B.expression.rightExpression = 100;
//将实例添加到引擎
引擎.AddInstance(obj1);
引擎.AddInstance(obj2);
while (true)
{
System.Console.WriteLine("---------------------------------");
System.Console.WriteLine("引擎中的实例:");
foreach (object obj in 引擎.getInstances().Keys)
{
string insID = obj.ToString();
string insStd = 引擎.getInstanceState(insID);
System.Console.WriteLine(insID + ":" + insStd);
}
System.Console.WriteLine("---------------------------------");
System.Console.WriteLine("请输入要下一步的实例号:[exit为退出]");
string s = System.Console.ReadLine();
if (s == "exit") { break; }
引擎.ExecuteNextNode(s);
}
}
}
数据的持久化
光实现流程控制是不够的,我们还需要流程的持久化功能,这也不难,用如下方式就可以了
class Program
{
static void Main(string[] args)
{
myData data1 = new myData();
data1.x = 123;
data1.y = 456;
data1.saveToFile(@"c:\data.xml");
myData data2 = new myData();
data2.loadFromFile(@"c:\data.xml");
System.Console.WriteLine("data2[x:{0},y:{1}]",data2.x,data2.y );
System.Console.Read();
}
}
//数据
[System.Serializable]
public class myData
{
public int x
{
get; set;
}
public int y
{
get; set;
}
public void saveToFile(string path)
{
System.Xml.Serialization.XmlSerializer xs;
xs = new System.Xml.Serialization.XmlSerializer(typeof(myData));
System.IO.FileStream file = new System.IO.FileStream(path, System.IO.FileMode.Create);
xs.Serialize(file, this);
file.Flush();
file.Close();
}
public void loadFromFile(string path)
{
System.Xml.Serialization.XmlSerializer xs;
xs = new System.Xml.Serialization.XmlSerializer(typeof(myData));
System.IO.FileStream file = new System.IO.FileStream(path, System.IO.FileMode.Open);
myData data = (myData)xs.Deserialize(file);
this.x = data.x;
this.y = data.y;
file.Close();
}
}
如果自已做,还要做些什么
为了修改方便,我们应该提供一个可以基于配置文件运行流程的接口,这个也可实现,当时我就已经做出来了
为了设计方便,我们应该提供一个可视化设计流程的UI,这个也可实现,当时我就已经做出来了
如果不是单机运行,我们还应该提供一个网络访问的接口,这个也可实现,当时我就已经做出来了
还有,流程可能要对数据库操作,我们应该提供一套事务处理案,
在这里,我遇到了问题,当时我的唯一选择是COM+,在用VB开发时,我就用COM+ ,
其实COM+并不好用,我一直想有一个DCOM 与 COM+ 结合的东西,而我当时的选择是COM+ 与 Remoting ,我不喜欢这个组合,
当时我想回到以前用VB开发DCOM的方式做,而组件事务部分就不要用,用传统的数据库事务.
这时,WF出现了,WF提供了上面我所说有全部功能,另外WF + WCF 的组合是我非常欢的(早期我的例子都是WF+ Remoting的,2007年后的例子都是WF+ WCF的)
而另一个成员WPF也不错,让我找到了xml + xslt 的感觉,对了,还有点 DHTML behaviors 的感觉,(跑题了,不说了)
总结我们为什么需要WF,因为不选WF,有很多功能都要自己去实现,很麻烦
除非
一,你要实现的这个功能确实太简单
二,你把这个功能的实现过程想的太简单
【本文由:香港云服务器 http://www.558idc.com/ne.html网络转载请说明出处】