ESFramework介绍之(9)-- 插件对(Addin Pair)调试“框架”

使用ESFramework开发C/S(通常为4层、3层也没问题)应用,当需要增加一项新的业务时,我们需要做的仅仅是开发两个插件,一个是服务端的业务功能插件(FunAddin),一个是客户端插件(PassiveAddin),这两个插件合在一起称为Addin Pair。开发这两个插件,只需要关注于业务,而其它与业务无关的比如网络通信、加密、数据安全,都不用管。ESFramework很好的将这些关注点分离开来,使得写“业务”插件的程序员的工作变得非常单纯,在ESFramework介绍之(8)-- 客户端插件IPassiveAddin一文给出的一个开发服务端功能插件和客户端插件的示例中,大家应该已经体会到这点了。

正如上文结尾处提到,当增加一项新的业务,调试包含了这个新业务实现的插件对(AddinPair)时非常麻烦,因为在ESFramework 4层架构中,服务端功能插件加载于功能服务器(FS)上,客户端插件加载在客户端应用程序上,中间的通信还经过了应用服务器(AS)。这样就要将ASFSClient都启动起来,才能对插件Pair进行调试,并且在这样调试的过程中,很多其它的因素会分散我们的注意力,比如多线程的影响、消息Hook的影响等等,这使得调试Addin Pair并不轻松,正是由于这个原因,促使我开发一个插件调试框架来简化这个麻烦的过程。

我的想法是,在VS.NET调试模式中运行这个“插件调试框架”(一个winForm应用程序),加载要调试的Addin Pair,然后,启动“业务操作窗体”显示出来,后续的交互将在两个插件之间直接进行通信,而VS.NET提供了我们跟踪到加载的插件的源码中的能力,这样就可以调试Addin Pair了。“插件调试框架”应用程序的主界面如下:

ESFramework介绍之(9)-- 插件对(Addin Pair)调试“框架”

测试模式中的“异常(功能服务器掉线)”用于模拟找不到对应服务端功能插件的情况。

我们知道,客户插件(PassiveAddin)通过IServerAgent来发送请求获取回复,在客户端应用程序中,IServerAgent是对底层TcpUdp的封装。在“插件调试框架”我们提供一个IServerAgent的实现给要调试的PassiveAddin使用,ESFramework给出的实现是AddinBridge类,它实现了IServerAgent接口,并且把PassiveAddin提交的请求直接提交给已加载的业务功能插件处理。AddinBridge实现如下:

AddinBridge
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->1///<summary>
2///AddinBridge用于将服务端插件和对应的客户端插件桥接起来,进行调试。
3///zhuweisky
4///</summary>
5publicclassAddinBridge:IServerAgent
6{
7publicAddinBridge()
8{
9}
10
11#regionProperty
12#regionFunAddinManagement
13privateIAddinManagementfunAddinManagement=null;
14publicIAddinManagementFunAddinManagement
15{
16set
17{
18this.funAddinManagement=value;
19}
20}
21
22
23#endregion
24
25#regionTestMode
26privateTestModetestMode=TestMode.Normal;
27publicTestModeTestMode
28{
29set
30{
31this.testMode=value;
32}
33}
34#endregion
35
36#endregion
37
38#regionIServerAgent成员
39publicNetMessageCommitRequest(MessagerequestMsg,DataPrioritydataPriority,boolcheckRespond)
40{
41if(this.testMode==ESFramework.Addins.TestMode.FSOffline)
42{
43requestMsg.Header.MessageBodyLength=0;
44requestMsg.Header.Result=ServiceResultType.ServiceIsNotExist;
45returnnewNetMessage(requestMsg.Header,null);
46}
47
48foreach(IFunAddinfunAddininthis.funAddinManagement.AddinList)
49{
50if(funAddin.ServiceKey==requestMsg.Header.ServiceKey)
51{
52//交给功能插件处理
53returnfunAddin.DealRequestMessage(requestMsg.ToNetMessage());
54}
55}
56
57requestMsg.Header.MessageBodyLength=0;
58requestMsg.Header.Result=ServiceResultType.ServiceIsNotExist;
59returnnewNetMessage(requestMsg.Header,null);
60}
61
62publicNetMessageCommitRequest(MessagerequestMsg,DataPrioritydataPriority,intexpectResServiceKey)
63{
64returnthis.CommitRequest(requestMsg,dataPriority,true);
65}
66
67#endregion
68}
69
70///<summary>
71///调试模式
72///</summary>
73publicenumTestMode
74{
75Normal,FSOffline
76}



AddinBridge
借助了IAddinManagement(插件管理器)来管理已加载的业务功能插件。

有了
AddinBridge的支持,“插件调试框架”的实现就非常容易了,我将上图主界面中的按钮点击事件源码列在下面:

private AddinBridgeserverAgent = new AddinBridge();
private IPassiveAddinpassiveAddin = null ;
按钮事件处理
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->1 privatevoidbutton_server_Click(objectsender,System.EventArgse)
2{
3this.textBox_server.Text=FileHelper.GetFileToOpen("请选择服务端插件",".dll");
4IAddinManagementaddinManager=newAddinManagement();
5stringmsg=null;
6boolsucceed=addinManager.LoadNewAddin(this.textBox_server.Text,outmsg);
7if(!succeed||(addinManager.AddinList.Count==0))
8{
9MessageBox.Show(msg+"请重新选择插件!");
10return;
11}
12
13this.serverAgent.FunAddinManagement=addinManager;
14}
15
16privatevoidbutton_passive_Click(objectsender,System.EventArgse)
17{
18this.textBox_passive.Text=FileHelper.GetFileToOpen("请选择客户端插件",".dll");
19IAddinManagementaddinManager=newAddinManagement();
20stringmsg=null;
21boolsucceed=addinManager.LoadNewAddin(this.textBox_passive.Text,outmsg);
22if(!succeed||(addinManager.AddinList.Count==0))
23{
24MessageBox.Show(msg+"请重新选择插件!");
25return;
26}
27
28this.passiveAddin=(IPassiveAddin)addinManager.AddinList[0];
29
30this.button_bind.Enabled=true;
31}
32
33privatevoidbutton_bind_Click(objectsender,System.EventArgse)
34{
35this.button_server.Enabled=false;
36this.button_passive.Enabled=false;
37this.button_start.Enabled=true;
38this.button_bind.Enabled=false;
39}
40
41privatevoidbutton_start_Click(objectsender,System.EventArgse)
42{
43if(this.radioButton_normal.Checked)
44{
45this.serverAgent.TestMode=TestMode.Normal;
46}
47else
48{
49this.serverAgent.TestMode=TestMode.FSOffline;
50}
51
52//通过反射创建客户业务操作窗体
53FormaddinForm=(Form)Activator.CreateInstance(this.passiveAddin.AddinFormType);
54((IPassiveAddinForm)addinForm).Initialize(this.serverAgent,"000000");
55addinForm.Show();
56}
57
58privatevoidbutton_reset_Click(objectsender,System.EventArgse)
59{
60this.textBox_passive.Clear();
61this.textBox_server.Clear();
62
63this.serverAgent.FunAddinManagement=null;
64this.passiveAddin=null;
65
66this.button_server.Enabled=true;
67this.button_passive.Enabled=true;
68this.button_start.Enabled=false;
69this.button_bind.Enabled=false;
70}
71

你可以在54行代码处添加断点,然后就可以跟入两个插件的源码中调试了。
需要注意的是,为了VS.NET能顺利的进入插件的源码,在加载插件时,最好直接加载插件工程Debug目录下的插件dll。

感谢关注!

转到:ESFramework 可复用的通信框架(序)

你可能感兴趣的:(framework)