博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

无代码的工作流创作模式

Posted on 2009-02-15 16:10  生鱼片  阅读(3977)  评论(21编辑  收藏  举报

工作流创作模式

WF中有三种工作流创作模式:

仅限代码:纯使用代码的方式,比如我们创建一个Workflow1.会产生Workflow1.cs和Workflow1.Desiger.cs两个文件。后者是自动生成的。前者是我们
实现逻辑和设计工作流的地方。如果有规则的话,会产生一个序列化的.rules文件。当项目生成的时候,该.rules文件会作为程序集的嵌入式资源。这种
方式在运行时只能通过动态更新来更改.

代码分离:.xoml格式,这种方式的工作流序列化后保存在一个以.xoml为扩展名的文件中,它的代码保存在.xoml.cs中。这种模式在生成的时候会先由
工作流编译器从.xoml文件生成临时的C#类,在和.xoml.cs一起编译。

无代码:只有一个.xoml文件。这种模式在VS模板中是不支持的,在这种模式下只能使用已经存在的工作流类型和成员。请看下图:

NoCode

从上图中我们可以很清楚的该模式的特点,这种模式有很大的灵活性,可以通过宿主程序将工作流标记文件加载到工作流运行时引擎。不需要重新编
译整个工作流。我们下面来说明如何使用该种方式。

1.首先我们自定义一个工作流基类提供工作流中需要的属性和方法,代码如下:

using System;
using System.Workflow.Activities;
namespace CaryWFLib
{
    public class CaryBaseWorkflow : SequentialWorkflowActivity
    {
        public int Number { get; set; }

        public void Condition(object sender, ConditionalEventArgs e)
        {
            e.Result = (Number > 0);
        }
    }
}
2.然后我们实现一个自定义活动CaryPrintActivity完成逻辑部分,主要功能输出Message,代码如下:
namespace CaryWFLib
{
    public partial class CaryPrintActivity: Activity
    {
        public static DependencyProperty MessageProperty
            = System.Workflow.ComponentModel.DependencyProperty.Register(
                "Message", typeof(String), typeof(CaryPrintActivity));

        [Description("A string message to write")]
        [Category("Pro Workflow")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public String Message
        {
            get
            {
                return ((String)(base.GetValue(CaryPrintActivity.MessageProperty)));
            }
            set
            {
                base.SetValue(CaryPrintActivity.MessageProperty, value);
            }
        }

        public CaryPrintActivity()
        {
            InitializeComponent();
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (Message != null)
            {
                Console.WriteLine(Message);
            }
            return base.Execute(executionContext);
        }
    }
}

3.然后我们来实现无代码的工作流部分,代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<ns0:CaryBaseWorkflow
x:Name="CaryNoCodeWorkflow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"
xmlns:ns0="clr-namespace:CaryWFLib;Assembly=CaryWFLib">
    <IfElseActivity x:Name="ifElseActivity1">
        <IfElseBranchActivity x:Name="ifElseBranchActivity1">
            <IfElseBranchActivity.Condition>
                <CodeCondition Condition="{ActivityBind Name=CaryNoCodeWorkflow,Path=Condition}" />
            </IfElseBranchActivity.Condition>
            <ns0:CaryPrintActivity Message="您输入的数字大于0" x:Name="caryPrintActivity1" />
        </IfElseBranchActivity>
        <IfElseBranchActivity x:Name="ifElseBranchActivity2">
            <ns0:CaryPrintActivity Message="您输入的数字小于等于0" x:Name="caryPrintActivity2" />
        </IfElseBranchActivity>
    </IfElseActivity>
</ns0:CaryBaseWorkflow>

注意
3.1.根节点为ns0:CaryBaseWorkflow,和活动条件的绑定部分。
3.2.无代码的工作流创作模式下不能包含X:Class属性。
3.3.如果规则为声明性规则即.rules的形式,上面的条件部分应该为:
<RuleConditionReferenceConditionName="Condition" />

3.4.需要将该工作流文件属性的生成操作设置为无。

4.宿主部分:

namespace NoCodeWorkflow
{
    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(); }; Dictionary<String, object> paras = new Dictionary<string, object>(); paras.Add("Number", 2); try { //XmlReader reader = XmlReader.Create("..\\..\\CaryNoCodeWorkflow.xoml"); XmlReader reader = XmlReader.Create("..\\..\\CaryNoCodeRulesWorkflow.xoml"); XmlReader readerRule = XmlReader.Create("..\\..\\CaryNoCodeRulesWorkflow.rules"); //WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader, null, paras); WorkflowInstance instance = workflowRuntime.CreateWorkflow(reader, readerRule, paras); instance.Start(); } catch (WorkflowValidationFailedException ex) { foreach (ValidationError error in ex.Errors) { Console.WriteLine(error.ErrorText); } } catch (Exception ex) { Console.WriteLine(ex.Message); } waitHandle.WaitOne(); } } } }
在宿主程序中,我们使用workflowRuntime.CreateWorkflow的另一种重载。最后结果如下:
NoCode1