经典场景猫叫、老鼠跑、主人醒之工作流实现
相信大家都遇到过用c#实现猫叫、老鼠跑、主人醒。这个已经几乎成了介绍c#事件时候的一个典型例子。今天我打算用wf中状态机工作流来实现这个场景。这里面的人物是<<猫和老鼠>>中的Jerry和Tom。先来下其中部分效果:
感觉咋样?可能有人觉得这里猫叫、老鼠跑、主人醒在经典场景中应该是连贯的这里应该用状态机工作流是不是有点不好,那么谁去响应handleExternalEventActivity类型的活动呢?看下下面的正常流程:
老鼠出现在洞口--->猫看见老鼠--->猫叫--->老鼠跑--->猫追--->追到老鼠--->主人表扬
这个流程中,需要宿主响应的是:猫看见老鼠、老鼠跑、猫追到老鼠。是吧,是不是有点蒙。看下状态机工作流图:
1、初始化
这个不用多说,调用了外部方法,实现老鼠出现
2、猫看见老鼠 先等待猫看见老鼠事件发生,然后判断猫是否要想抓老鼠。
3、老鼠跑,主人醒 老鼠听到猫叫后,反应一段时间发生逃跑事件,接着用调用外部方法猫去追老鼠。
4、老鼠捉住猫 先等待猫追到老鼠事件发生,根据情况,主人给予表现。
5、结束
是的,大家应该发现了。这里的状态比较简单,因为考虑的因素不是很多,状态机往往一个状态会有多种路径的选择。比如这个案例中:如果老鼠出现在洞口,猫一直没看见,那是怎样?如果猫看见老鼠,但它确实懒的去捉它,这又如何表示?也许,等猫追到老鼠跑主人面前,主人不会有任何反应。这些都代表着多种事件触发带来的不同状态转换。有时间针对这个场景再完善完善。
关于工作流和wf的基础概念不了解得可以链接到这。http://www.cnblogs.com/sharezone/archive/2009/05/15/1457644.html
通信接口代码:
public interface ICMMControl
{
// Workflow to host communication
/// <summary>
/// 主人表扬
/// </summary>
void WorkFlowInit();
/// <summary>
/// 猫叫
/// </summary>
void CatWow();
/// <summary>
/// 猫追
/// </summary>
void CatCatch();
/// <summary>
/// 主人表扬
/// </summary>
void MasterSay();
// Host to workflow communication
/// <summary>
/// 猫追上了老鼠
/// </summary>
event EventHandler<CatCatchMouseEventArgs> CatCatchMouse;
/// <summary>
/// 猫看见老鼠
/// </summary>
event EventHandler<CatSeeMouseEventArgs> CatSeeMouse;
/// <summary>
/// 老鼠跑主人醒
/// </summary>
event EventHandler<MouseRunAndMasterWakeArgs> MouseRunAndMasterWake;
}
通讯协议实现类代码:
public class CMMConnector:ICMMControl
{
protected static CMMDataService _service = null;
protected static object _syncLock = new object();
public event EventHandler<MouseRunAndMasterWakeArgs> MouseRunAndMasterWake;
public event EventHandler<CatSeeMouseEventArgs> CatSeeMouse;
public event EventHandler<CatCatchMouseEventArgs> CatCatchMouse;
public static CMMDataService CmmDataService
{
get { return _service; }
set
{
lock (_syncLock)
{
_service = value;
}
}
}
public void CatWow()
{
_service.RaiseCatWowEvent();
}
public void WorkFlowInit()
{
_service.RaiseWorkFlowInitEvent();
}
public void CatCatch()
{
_service.RaiseCatCatchEvent();
}
public void MasterSay()
{
_service.RaiseMasterSayEvent();
}
public void RaiseCatSeeMouse(Guid instanceID, bool flag)
{
if (CatSeeMouse != null)
{
CatSeeMouse(null, new CatSeeMouseEventArgs(instanceID,flag));
}
}
public void RaiseCatCatchMouse(Guid instanceID)
{
if (CatCatchMouse != null)
{
CatCatchMouse(null, new CatCatchMouseEventArgs(instanceID));
}
}
public void RaiseMouseRunAndMasterWake(Guid instanceID)
{
if (MouseRunAndMasterWake != null)
{
MouseRunAndMasterWake(null, new MouseRunAndMasterWakeArgs(instanceID));
}
}
}
通信服务类代码:
public class CMMDataService
{
protected static WorkflowRuntime _workflowRuntime = null;
protected static ExternalDataExchangeService _dataExchangeService = null;
protected static CMMConnector _dataConnector = null;
protected static object _syncRoot = new object();
public event EventHandler CatWow;
public event EventHandler CatCatch;
public event EventHandler MasterSay;
public event EventHandler WorkflowInit;
private Guid _instanceID = Guid.Empty;
public Guid InstanceID
{
get { return _instanceID; }
set { _instanceID = value; }
}
public static CMMDataService CreateDataService(Guid instanceID, WorkflowRuntime workflowRuntime)
{
lock (_syncRoot)
{
if (_workflowRuntime == null)
{
_workflowRuntime = workflowRuntime;
}
if (_dataExchangeService == null)
{
_dataExchangeService = new ExternalDataExchangeService();
_workflowRuntime.AddService(_dataExchangeService);
}
CMMConnector dataConnector = (CMMConnector)workflowRuntime.GetService(typeof(CMMConnector));
if (dataConnector == null)
{
_dataConnector = new CMMConnector();
_dataExchangeService.AddService(_dataConnector);
}
else
{
_dataConnector = dataConnector;
}
CMMDataService workflowDataService = new CMMDataService(instanceID);
CMMConnector.CmmDataService = workflowDataService;
return workflowDataService;
}
}
public static CMMDataService GetRegisteredWorkflowDataService()
{
lock (_syncRoot)
{
CMMDataService workflowDataService = CMMConnector.CmmDataService;
if (workflowDataService == null)
{
throw new Exception("Error configuring data service...service cannot be null.");
}
return workflowDataService;
}
}
private CMMDataService(Guid instanceID)
{
_instanceID = instanceID;
CMMConnector.CmmDataService = this;
}
~CMMDataService()
{
_workflowRuntime = null;
_dataExchangeService = null;
_dataConnector = null;
}
public void RaiseCatWowEvent()
{
if (_workflowRuntime == null)
_workflowRuntime = new WorkflowRuntime();
_workflowRuntime.GetWorkflow(_instanceID); // loads persisted workflow instances
if (CatWow != null)
{
CatWow(this, null);
}
}
public void RaiseWorkFlowInitEvent()
{
if (_workflowRuntime == null)
_workflowRuntime = new WorkflowRuntime();
_workflowRuntime.GetWorkflow(_instanceID); // loads persisted workflow instances
if (WorkflowInit != null)
{
WorkflowInit(this, null);
}
}
public void RaiseCatCatchEvent()
{
if (_workflowRuntime == null)
_workflowRuntime = new WorkflowRuntime();
_workflowRuntime.GetWorkflow(_instanceID);
if (CatCatch != null)
{
CatCatch(this, null);
}
}
public void RaiseMasterSayEvent()
{
if (_workflowRuntime == null)
_workflowRuntime = new WorkflowRuntime();
_workflowRuntime.GetWorkflow(_instanceID);
if (MasterSay != null)
{
MasterSay(this, null);
}
}
}