工作流包装

来源:互联网 发布:淘宝双十一外围会场 编辑:程序博客网 时间:2024/05/17 01:33
 

工作流包装

1.         运行时包装

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Workflow.Runtime;

 

namespace Nocturne.Workflow.Hosting

{

 public class WorkflowRuntimeManager:IDisposable

     {

        private WorkflowRuntime _workflowRuntime;

        private Dictionary<Guid, WorkflowInstanceWrapper> _workflows = new Dictionary<Guid, WorkflowInstanceWrapper>();

 

     

        public WorkflowRuntimeManager(WorkflowRuntime instance)

        {

            _workflowRuntime = instance;

            if (instance == null)

            { throw new NullReferenceException("需要一个非空的 WorkflowRuntime 实例"); }

            // 提交所有的工作流事件

            SubscribeToEvents(instance);

        }

        /// <summary>

        /// 创建并启动一个工作流。

        /// </summary>

        /// <param name="workflowType">待启动的工作流类型</param>

        ///  <param name="parameters">入口参数</param>

        /// <returns>包装在一个WorkflowInstanceWrapper里的工作流实例</returns>

        public WorkflowInstanceWrapper StartWorkflow(Type workflowType, Dictionary<string, object> parameters)

        {

            WorkflowInstance instance = _workflowRuntime.CreateWorkflow(workflowType, parameters);

            WorkflowInstanceWrapper wrapper = AddWorkflowInstance(instance);

            instance.Start();

            return wrapper;

        }

        #region        公共属性和事件

            /// <summary>

        /// 获取WorkflowRuntime实例

        /// </summary>

        public WorkflowRuntime WorkflowRuntime

        { get { return _workflowRuntime; } }

        /// <summary>

        /// 获取工作流实例包装的一个字典

        /// </summary>

        public Dictionary<Guid, WorkflowInstanceWrapper> Workflows

        { get { return _workflows; } }

        /// <summary>

        /// 记录该类的日志信息的事件

        /// </summary>

        public event EventHandler<WorkflowLogEventArgs> MessageEvent;

        #endregion

        #region 工作流集合管理

        /// <summary>

        ///  从工作流字典中移除某个实例

        /// </summary>

        /// <param name="workflowId"></param>

        public void ClearWorkflow(Guid workflowId)

        { if (_workflows.ContainsKey(workflowId))

        { _workflows.Remove(workflowId); }

        }

        /// <summary>

        /// 从字典中清除所有的工作流

        /// </summary>

        public void ClearAllWorkflows() {

            _workflows.Clear();

        }

        /// <summary>

        /// 向字典中添加一个新的工作流实例

        /// </summary>

        /// <param name="instance"></param>

        /// <returns></returns>

        private WorkflowInstanceWrapper AddWorkflowInstance(WorkflowInstance instance)

        { WorkflowInstanceWrapper wrapper = null;

            if (!_workflows.ContainsKey(instance.InstanceId))

            { wrapper = new WorkflowInstanceWrapper(instance);

                _workflows.Add(wrapper.Id, wrapper);

            } return wrapper;

        }

        /// <summary>

        /// 依据Guid查找工作流实例

        /// </summary>

        /// <param name="workflowId"></param>

        /// <returns></returns>

        public WorkflowInstanceWrapper FindWorkflowInstance(Guid workflowId)

        { WorkflowInstanceWrapper result = null;

            if (_workflows.ContainsKey(workflowId))

            { result = _workflows[workflowId]; }

            return result;

        }

        /// <summary>

        /// 等待所有的工作流实例完成

        /// </summary>

        /// <param name="msecondsTimeout"></param>

        public void WaitAll(int msecondsTimeout)

        {

            if (_workflows.Count > 0)

            {

                    WaitHandle[] handles = new WaitHandle[_workflows.Count];

                int index = 0;

                foreach (WorkflowInstanceWrapper wrapper in _workflows.Values)

                {

                    handles[index] = wrapper.WaitHandle;

                    index++;

                }

                WaitHandle.WaitAll(handles, msecondsTimeout, false);

            }

        }

        #endregion

        #region IDisposable Members

        /// <summary>

        ///  销毁工作流运行时

        /// </summary>

        public void Dispose()

        {

            if (_workflowRuntime != null)

            {

                _workflowRuntime.StopRuntime();

                _workflowRuntime.Dispose();

            }

            ClearAllWorkflows();

        }

        #endregion

        #region 工作流事件处理

        /// <summary>

        /// 订阅我们所有关心的事件

        /// </summary>

        /// <param name="runtime"></param>

        private void SubscribeToEvents(WorkflowRuntime runtime)

        {

            runtime.Started += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Started);

            runtime.Stopped += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Stopped);

            runtime.WorkflowAborted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowAborted);

            runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(runtime_WorkflowCompleted);

            runtime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(runtime_WorkflowCreated);

            runtime.WorkflowIdled += new EventHandler<WorkflowEventArgs>(runtime_WorkflowIdled);

            runtime.WorkflowLoaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowLoaded);

            runtime.WorkflowPersisted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowPersisted);

            runtime.WorkflowResumed += new EventHandler<WorkflowEventArgs>(runtime_WorkflowResumed);

            runtime.WorkflowStarted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowStarted);

            runtime.WorkflowSuspended += new EventHandler<WorkflowSuspendedEventArgs>(runtime_WorkflowSuspended);

            runtime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(runtime_WorkflowTerminated);

            runtime.WorkflowUnloaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowUnloaded);

        }

        void runtime_Started(object sender, WorkflowRuntimeEventArgs e)

        {

            LogStatus(Guid.Empty, "Started");

        }

        void runtime_Stopped(object sender, WorkflowRuntimeEventArgs e)

        {

            LogStatus(Guid.Empty, "Stopped");

        }

        void runtime_WorkflowCreated(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowCreated");

        }

        void runtime_WorkflowStarted(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowStarted");

        }

        void runtime_WorkflowIdled(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowIdled");

        }

        void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowCompleted");

            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);

            if (wrapper != null)

            {

                wrapper.OutputParameters = e.OutputParameters;

                wrapper.StopWaiting();

            }

        }

        void runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowTerminated");

            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);

            if (wrapper != null)

            {

                wrapper.Exception = e.Exception;

                wrapper.StopWaiting();

            }

        }

        void runtime_WorkflowSuspended(object sender, WorkflowSuspendedEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowSuspended");

            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);

            if (wrapper != null) {

                wrapper.ReasonSuspended = e.Error;

            }

        }

        void runtime_WorkflowResumed(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowResumed");

        }

        void runtime_WorkflowPersisted(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowPersisted");

        }

        void runtime_WorkflowLoaded(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowLoaded");

        }

        void runtime_WorkflowAborted(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowAborted");

            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);

            if (wrapper != null)

            {

                wrapper.StopWaiting();

            }

        }

        void runtime_WorkflowUnloaded(object sender, WorkflowEventArgs e)

        {

            LogStatus(e.WorkflowInstance.InstanceId, "WorkflowUnloaded");

        }

        private void LogStatus(Guid instanceId, String msg)

        {

            if (MessageEvent != null)

        {

            String formattedMsg;

              if (instanceId == Guid.Empty)

            {

                formattedMsg = String.Format("Runtime - {0}", msg);

            }

 

        else

            {

                formattedMsg = String.Format("{0} - {1}", instanceId, msg);

            }

                // 引发事件

                MessageEvent(this, new WorkflowLogEventArgs(formattedMsg));

            }

        }

        #endregion

    }

    /// <summary>

    /// 在管理类中用来记录日志信息的EventArgs

    /// </summary>

    public class WorkflowLogEventArgs : EventArgs

    {

        private string _msg = string.Empty;

        public WorkflowLogEventArgs(string msg)

        {

            _msg = msg;

        }             

        public string Message

        { get { return _msg; } }

    }

}

2.         工作流实例包装

using System;

using System.Collections.Generic;

using System.Threading;

using System.Workflow.Runtime;

namespace Nocturne.Workflow.Hosting

{

    /// <summary>

    ///  工作流实例的容器

    ///  </summary>

    [Serializable]

    public class WorkflowInstanceWrapper

    {

        private WorkflowInstance _workflowInstance;

        private ManualResetEvent _waitHandle = new ManualResetEvent(false);

        private Dictionary<string, object> _outputParameters = new Dictionary<string, object>();

        private Exception _exception;

        private string _reasonSuspended = string.Empty;

        public WorkflowInstanceWrapper(WorkflowInstance instance)

        { _workflowInstance = instance; }

        #region 公开属性与方法

        /// <summary>

        /// 获取工作流实例的 ID

        /// </summary>

        public Guid Id

        {

            get

            {

                if (_workflowInstance != null) { return _workflowInstance.InstanceId; }

                else { return Guid.Empty; }

            }

        }

        /// <summary>

        /// 输出参数的集合

        /// </summary>

        public Dictionary<string, object> OutputParameters

        { get { return _outputParameters; } set { _outputParameters = value; } }

        /// <summary>

        /// 一个等待句柄。宿主应用程序可以使用它,挂起

        /// 进程直到工作流完成。

        /// </summary>

        public ManualResetEvent WaitHandle

        { get { return _waitHandle; } set { _waitHandle = value; } }

        /// <summary>

        ///  工作流可能抛出的异常对象

        ///   </summary>

        public Exception Exception

        { get { return _exception; } set { _exception = value; } }

        /// <summary>

        /// 工作流挂起的原因

        /// /// </summary>

        public string ReasonSuspended

        { get { return _reasonSuspended; } set { _reasonSuspended = value; } }

        /// <summary>

        /// 真实的工作流实例

        /// </summary>

        public WorkflowInstance WorkflowInstance

        { get { return _workflowInstance; } }

        /// <summary>

        /// 工作流完成的信号,宿主应用程序可以停止等待

        /// </summary>

        public void StopWaiting()

        {

            _waitHandle.Set();

        }

        #endregion

    }

}

 

3.         测试程序

using System;

using System.Collections.Generic;

using System.Text;

using System.Workflow.Runtime;

using System.Workflow.Runtime.Hosting;

using Nocturne.Workflow.Hosting;

namespace ConsoleHostingManaged

{

    /// <summary>

    ///  使用自定义封装类来host工作流

    ///   </summary> class WorkflowTest

    {

    /// Run 方法将在 Main 方法启动之后被执行,该方法创建一个 WorkflowRuntimeManager 的实例而启动,

    ///  使用 using 的目的在于一旦离开这个语句块,就可以自动调用 Dispose 方法来销毁对象,前面实现

    /// IDisposable 接口的意义就在于此。

    /// WorkflowRuntimeManager 构造函数被传入一个 WorkflowRuntime 类的实例。这就是我们设计管理类

    /// 的目的,从外部构造 WorkflowRuntime,以此来提供附加的过占星。

 

/// 一个事件句柄被作为 WorkflowRuntimeManager.MessageEvent 添加。此事件在处理 WorkflowRuntime

/// 事件的时候会被出发。这段代码仅仅是简单的将信息输出到屏幕上

/// <summary>

/// 启动工作流

/// </summary>

   public static void Run()

{

    Console.WriteLine("使用 persistence 服务运行测试");

    using (WorkflowRuntimeManager manager = new WorkflowRuntimeManager(new WorkflowRuntime()))

{

    // 添加一个事件句柄记录日志

    manager.MessageEvent += delegate(object sender, WorkflowLogEventArgs e){ Console.WriteLine(e.Message); }

 

     // 创建完 WorkflowRuntime 及其包装之后,我们采用私有的 AddServices 方法向工作流运行

    // 时添加服务。

    AddServices(manager.WorkflowRuntime);

    // 启动工作流运行时。注意这一步并非必须,如果忽略这条语句,工作流运行时同样会自动运

    // 行。但是所有的核心服务必须在启动运行时引擎之前声明,如果我们在调用这条语句之后

    // (或者被自动调用了)才添加核心服务(也就是上面那句话),编译器会抛出异常。

    manager.WorkflowRuntime.StartRuntime();

    // 当核心服务添加到运行时引擎之后,就可以运行工作流了。Dictionary 就是用来传送参数的

    // 桥梁

    Dictionary<string, object> wfArguments = new Dictionary<string, object>();

    wfArguments.Add("InputString", "One");

    manager.StartWorkflow(typeof(SharedWorkflows.Workflow1), wfArguments);

    // 启动另一个实例。

    wfArguments.Clear();

    wfArguments.Add("InputString", "two");

    manager.StartWorkflow(typeof(SharedWorkflows.Workflow1),wfArguments);

    wfArguments.Clear();

    wfArguments.Add("InputString","three");

    manager.StartWorkflow(typeof(SharedWorkflows.Workflow1),wfArguments);

    // 等待所有工作流实例完成

manager.WaitAll(15000);

// 显示所有工作流实例的结果。由于这些工作流是存储在Dictionary里的,因此可以

// 使用 foreach 进行迭代

foreach(WorkflowInstanceWrapper wrapper in manager.Workflows.Values)

{ if (wrapper.OutputParameters.ContainsKey("Result"))

{ Console.WriteLine(wrapper.OutputParameters["Result"]); }

else

{ if (wrapper.Exception!=null)

{ Console.WriteLine("{0} - 异常: {1}",wrapper.Id,wrapper.Exception.Message); } } }

manager.ClearAllWorkflows(); } }

/// <summary>

/// 添加运行时引擎需要的服务

/// </summary>

/// <param name="instance"></param>

    private static void AddServices(WorkflowRuntime instance)

{

string connStringPersistence = string.Format("Initial Catalog={0}; Data Source={1}; Integrated Security={2};", "WorkflowPersistence", @"localhost/SQLEXPRESS", "SSPI");

instance.AddService(new SqlWorkflowPersistenceService(connStringPersistence, true, new TimeSpan(0, 2, 0), new TimeSpan(0, 0, 5)));

}

}

}