ESFramework介绍之(9)-- 插件对(Addin Pai
系统
1605 0
使用
ESFramework
开发
C/S
(通常为
4
层、
3
层也没问题)应用,当需要增加一项新的业务时,我们需要做的仅仅是开发两个插件,一个是服务端的业务功能插件(FunAddin),一个是客户端插件(
PassiveAddin
),这两个插件合在一起称为
Addin Pair
。开发这两个插件,只需要关注于业务,而其它与业务无关的比如网络通信、加密、数据安全,都不用管。
ESFramework
很好的将这些关注点分离开来,使得写“业务”插件的程序员的工作变得非常单纯,在
ESFramework
介绍之(
8
)--
客户端插件
IPassiveAddin
一文给出的一个开发服务端功能插件和客户端插件的示例中,大家应该已经体会到这点了。
正如
上文
结尾处提到,当增加一项新的业务,调试包含了这个新业务实现的插件对(
AddinPair
)时非常麻烦,因为在
ESFramework 4
层架构中,服务端功能插件加载于功能服务器(
FS
)上,客户端插件加载在客户端应用程序上,中间的通信还经过了应用服务器(AS)。这样就要将
AS
、
FS
、
Client
都启动起来,才能对插件
Pair
进行调试,并且在这样调试的过程中,很多其它的因素会分散我们的注意力,比如多线程的影响、消息
Hook
的影响等等,这使得调试
Addin Pair
并不轻松,正是由于这个原因,促使我开发一个插件调试框架来简化这个麻烦的过程。
我的想法是,在
VS.NET
调试模式中运行这个“插件调试框架”(一个
winForm
应用程序),加载要调试的
Addin Pair
,然后,启动
“业务操作窗体”显示出来,后续的交互将在两个插件之间直接进行通信,而
VS.NET
提供了我们跟踪到加载的插件的源码中的能力,这样就可以调试
Addin Pair
了。
“插件调试框架”应用程序的主界面如下:
测试模式中的“异常(功能服务器掉线)”用于模拟找不到对应服务端功能插件的情况。
我们知道,客户插件(
PassiveAddin
)通过
IServerAgent
来发送请求获取回复,在客户端应用程序中,
IServerAgent
是对底层
Tcp
或
Udp
的封装。在“插件调试框架”我们提供一个
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>
5
public
class
AddinBridge:IServerAgent
6
{
7
public
AddinBridge()
8
{
9
}
10
11
#region
Property
12
#region
FunAddinManagement
13
private
IAddinManagementfunAddinManagement
=
null
;
14
public
IAddinManagementFunAddinManagement
15
{
16
set
17
{
18
this
.funAddinManagement
=
value;
19
}
20
}
21
22
23
#endregion
24
25
#region
TestMode
26
private
TestModetestMode
=
TestMode.Normal;
27
public
TestModeTestMode
28
{
29
set
30
{
31
this
.testMode
=
value;
32
}
33
}
34
#endregion
35
36
#endregion
37
38
#region
IServerAgent成员
39
public
NetMessageCommitRequest(MessagerequestMsg,DataPrioritydataPriority,
bool
checkRespond)
40
{
41
if
(
this
.testMode
==
ESFramework.Addins.TestMode.FSOffline)
42
{
43
requestMsg.Header.MessageBodyLength
=
0
;
44
requestMsg.Header.Result
=
ServiceResultType.ServiceIsNotExist;
45
return
new
NetMessage(requestMsg.Header,
null
);
46
}
47
48
foreach
(IFunAddinfunAddin
in
this
.funAddinManagement.AddinList)
49
{
50
if
(funAddin.ServiceKey
==
requestMsg.Header.ServiceKey)
51
{
52
//
交给功能插件处理
53
return
funAddin.DealRequestMessage(requestMsg.ToNetMessage());
54
}
55
}
56
57
requestMsg.Header.MessageBodyLength
=
0
;
58
requestMsg.Header.Result
=
ServiceResultType.ServiceIsNotExist;
59
return
new
NetMessage(requestMsg.Header,
null
);
60
}
61
62
public
NetMessageCommitRequest(MessagerequestMsg,DataPrioritydataPriority,
int
expectResServiceKey)
63
{
64
return
this
.CommitRequest(requestMsg,dataPriority,
true
);
65
}
66
67
#endregion
68
}
69
70
///
<summary>
71
///
调试模式
72
///
</summary>
73
public
enum
TestMode
74
{
75
Normal,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
private
void
button_server_Click(
object
sender,System.EventArgse)
2
{
3
this
.textBox_server.Text
=
FileHelper.GetFileToOpen(
"
请选择服务端插件
"
,
"
.dll
"
);
4
IAddinManagementaddinManager
=
new
AddinManagement();
5
string
msg
=
null
;
6
bool
succeed
=
addinManager.LoadNewAddin(
this
.textBox_server.Text,
out
msg);
7
if
(
!
succeed
||
(addinManager.AddinList.Count
==
0
))
8
{
9
MessageBox.Show(msg
+
"
请重新选择插件!
"
);
10
return
;
11
}
12
13
this
.serverAgent.FunAddinManagement
=
addinManager;
14
}
15
16
private
void
button_passive_Click(
object
sender,System.EventArgse)
17
{
18
this
.textBox_passive.Text
=
FileHelper.GetFileToOpen(
"
请选择客户端插件
"
,
"
.dll
"
);
19
IAddinManagementaddinManager
=
new
AddinManagement();
20
string
msg
=
null
;
21
bool
succeed
=
addinManager.LoadNewAddin(
this
.textBox_passive.Text,
out
msg);
22
if
(
!
succeed
||
(addinManager.AddinList.Count
==
0
))
23
{
24
MessageBox.Show(msg
+
"
请重新选择插件!
"
);
25
return
;
26
}
27
28
this
.passiveAddin
=
(IPassiveAddin)addinManager.AddinList[
0
];
29
30
this
.button_bind.Enabled
=
true
;
31
}
32
33
private
void
button_bind_Click(
object
sender,System.EventArgse)
34
{
35
this
.button_server.Enabled
=
false
;
36
this
.button_passive.Enabled
=
false
;
37
this
.button_start.Enabled
=
true
;
38
this
.button_bind.Enabled
=
false
;
39
}
40
41
private
void
button_start_Click(
object
sender,System.EventArgse)
42
{
43
if
(
this
.radioButton_normal.Checked)
44
{
45
this
.serverAgent.TestMode
=
TestMode.Normal;
46
}
47
else
48
{
49
this
.serverAgent.TestMode
=
TestMode.FSOffline;
50
}
51
52
//
通过反射创建客户业务操作窗体
53
FormaddinForm
=
(Form)Activator.CreateInstance(
this
.passiveAddin.AddinFormType);
54
((IPassiveAddinForm)addinForm).Initialize(
this
.serverAgent,
"
000000
"
);
55
addinForm.Show();
56
}
57
58
private
void
button_reset_Click(
object
sender,System.EventArgse)
59
{
60
this
.textBox_passive.Clear();
61
this
.textBox_server.Clear();
62
63
this
.serverAgent.FunAddinManagement
=
null
;
64
this
.passiveAddin
=
null
;
65
66
this
.button_server.Enabled
=
true
;
67
this
.button_passive.Enabled
=
true
;
68
this
.button_start.Enabled
=
false
;
69
this
.button_bind.Enabled
=
false
;
70
}
71
你可以在54行代码处添加断点,然后就可以跟入两个插件的源码中调试了。
需要注意的是,为了VS.NET能顺利的进入插件的源码,在加载插件时,最好直接加载插件工程Debug目录下的插件dll。
感谢关注!
转到:
ESFramework 可复用的通信框架(序)
ESFramework介绍之(9)-- 插件对(Addin Pair)调试“框架”
更多文章、技术交流、商务合作、联系博主
微信扫码或搜索:z360901061
微信扫一扫加我为好友
QQ号联系: 360901061
您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。
【本文对您有帮助就好】元