一步一步学WF系列(七)——改善登录程序(上)
1. 温故而知新
还记得我们在一步一步学WF系列(四)中写的登陆程序么?如果忘记了,那就回去看看。
在这一节中,让我们去改善我们的登录程序。
最近一直在忙着找工作的事情,所以发文慢了些,还望各位见谅。
3. 引出话题
我之前一直在强调,工作流负责的是一个宏观工作,我们应该把他与整体设计外的,那些边边角角的细节隔离在外面。
我最近在这个系列的同时,还在写一个《重温设计模式》的系列文章,因此特别要强调针对接口编程的重要性。
好,从现在开始步入正题。
4. 回顾登录
让我们回顾一下原有的登陆程序,在原有的登陆项目中,我们把所有的工作都杂糅在了工作流中。
让我们看看我们曾经丑陋的代码:
Workflow2.cs:
private void codeActivity1_ExecuteCode(object sender, EventArgs e) { MessageBox.Show("用户名和密码不能为空"); } private void Validate(object sender, ConditionalEventArgs e) { e.Result = this.userName.Equals("admin") && this.userPassword.Equals("admin"); } private void codeActivity2_ExecuteCode(object sender, EventArgs e) { MessageBox.Show("登陆成功"); } private void codeActivity3_ExecuteCode(object sender, EventArgs e) { MessageBox.Show("用户名和密码不正确"); }我想,当时也许有人会有这个疑问,楼主,你这不是骗人么?用不用工作流有什么呢?你不过是把原有的应该在Winform后台写的东西拿到了工作流中去写罢了。
好,我们从现在开始改善我们这段丑陋的代码。
5. 登录设计
让我们先来想想我们在登录时的步骤,包括我们的做的和系统做的:
好,那么我们想,工作流负责的应该是一个宏观的过程,那么我们要把具体的细节给抽取出来,究竟什么是具体细节呢?
A. 用户的验证过程。(可能是连接数据库,可能是连接文件验证)
B. 反馈给客户的反馈信息。(可能是Response.Write,可能是MessageBox.Show)
好,抽取出了这两条,让我们想,是什么触发了这个工作流程,是我们点击登陆按钮的一刹那:
那么我们应该用一个事件去监听我们的登录按钮事件,当我们点击登录时便触发工作流。
分析结束,那就让我们看看我们的建模图:
由于本人的Visio功力实在有限,所以就用画图来画这些图了,我一定抓紧时间去练习Visio。
图画的不太好,我再来解释一下:
A. 用户首先输入用户名,密码,然后点击登录。
B. 这个时候触发了工作流的事件,并且向事件中传入我们所输入的信息。
C. 工作流根据我们所传入的信息去请求验证的接口,执行验证的代码。
D. 根据返回的结果,然后去请求相应的响应接口。
E. 最后将结果返回给用户。
分析结束,我们看到,这里面有个很重要的东西,就是工作流和外部的交互,好,那就让我们在改善登录程序前,先学习两个重要的活动。
6. HandlerExternalEvent
HandlerExternalEvent是我们接触的第一个事件类型的活动。事件类型就是通过某个事件才可以触发的活动。
我长话短说,这个活动的作用是在工作流的外部去调用工作流内部的方法,即HandlerExternalEvent的事件。
我在这里做一个小例子,然后结合代码为大家讲解。
首先让我们添加一个HandlerExternalEvent活动:
然后让我们新建一个类库,类库中包含一个接口,来做工作流和外部程序的一个交互:
namespace Interface { [ExternalDataExchange] public interface IEvent { event EventHandler<ExternalDataEventArgs> MyEvent1; } }这段代码,我们注意三个点:
A. ExternalDataExchange:将接口标记为本地服务接口,具有该特性才能被工作流识别。
B. 接口内部事件:工作流在内部将自身绑定到该事件,用户在外部通过该事件触发工作流内部方法。
C. ExternalDataEventArgs:标识使用HandlerExternalEventActivity活动引发事件时传递的参数。
好,接下来我们通过属性窗口将该事件绑定到工作流的HandlerExternalEventActivity中:
然后我们在外部去调用这个事件,看整个项目的完整代码:
Workflow1.cs:
public sealed partial class Workflow1 : SequentialWorkflowActivity { public Workflow1() { InitializeComponent(); } private void handleExternalEventActivity1_Invoked(object sender, ExternalDataEventArgs e) { MessageBox.Show("Success"); } }Winform1.cs:
public partial class Form1 : Form,IEvent { private WorkflowRuntime runtime; private ExternalDataExchangeService service; private WorkflowInstance instance; public Form1() { InitializeComponent(); runtime = new WorkflowRuntime(); service = new ExternalDataExchangeService(); runtime.AddService(service); service.AddService(this); runtime.StartRuntime(); } private void button1_Click(object sender, EventArgs e) { instance = runtime.CreateWorkflow(typeof(WorkflowConsoleApplication7.Workflow1)); instance.Start(); ExternalDataEventArgs args = new ExternalDataEventArgs(instance.InstanceId); MyEvent1(null, args); } #region IEvent 成员 public event EventHandler<ExternalDataEventArgs> MyEvent1; #endregion }7. CallExternalMethod
与上面的活动相反,这个活动的作用是通过这个事件去调用外部的代码。
同样,我们用代码来说话:
接下来,我们同样来新建一个类库,包含一个接口用来和外部程序进行交互:
不同的是,在HandlerExternalEvent的接口中是事件,而这个是方法:
namespace CallMethod { [ExternalDataExchange] public interface ICallExternalMethod { void CallExternalMethod(); } }这个和上面都是一个道理的,我就不多做解释了:
让我们直接看代码吧:
Winform2.cs:
public partial class Form2 : Form,ICallExternalMethod { private WorkflowRuntime runtime; private ExternalDataExchangeService service; private WorkflowInstance instance; public Form2() { InitializeComponent(); runtime = new WorkflowRuntime(); service = new ExternalDataExchangeService(); runtime.AddService(service); service.AddService(this); runtime.StartRuntime(); } #region ICallExternalMethod 成员 public void CallExternalMethod() { MessageBox.Show("调用了这个方法"); } #endregion private void button1_Click(object sender, EventArgs e) { instance = runtime.CreateWorkflow(typeof(WorkflowConsoleApplication7.Workflow2)); instance.Start(); } }8. 写在后面
本来想在这篇文章中完成对我们之前登录的改造,但是文章太长了大家好像都不太爱看,于是就还是分开写吧。
我们已经学习了如何让工作流和外部程序进行交互,那么我们大家就试着用这个去改善一下工作流吧?
你能么?
敬请期待下文:《一步一步学习WF系列(八)——改善登陆程序(下)》
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!