|
i> 脚本式
使用某种语言把插件的程序逻辑写成脚本代码。而这种语言可以是 Python ,或是其他现存的已经经过用户长时间考验的脚本语言。甚至,你可以自行设计一种脚本语言来配合你程序的特殊需要。当然,用当今最流行的 XML 是再合适不过了。
这种形式的特点在于,稍有点编程知识的用户就可以自行修改你的脚本( ^_^ 假如你不加密它的话)。我们无法论证这是好处还是坏处。因为,这种情况所造成的后果是不可预知的。
ii> 动态函数库 DLL
插件功能以动态库函数的形式存在。主程序通过某种渠道(插件编写者或某些工具)获得插件 DLL 中的函数签名,然后在合适的地方调用它们。用过 Matlab 的读者都知道, Matlab 中的各项功能几乎都是些动态链入的函数。
iii> 聚合式
顾名思义,就是把插件功能直接写成 EXE 。主程序除了完成自己的职责外,还负责调度这些“插件”。我不喜欢这种形式。这使插件与插件之间,主程序与插件之间(主要是这一点)的信息交流困难了许多。巴比伦塔的失败
[1] 从某种程度上讲就是
信息交流无法实现造成的。
iv> COM 组件
COM
[2] 的产生给这个世界增添了几分活力。只有
接口!我们的插件需要做的只是实现程序定义的接口。主程序不需要知道插件怎样实现预定的功能,它只需要通过接口访问插件,并提供主程序相关对象的接口。这样一来,主程序与各插件之间的信息交流就变得异常简单。并且,插件对于主程序来说是完全透明的。
|
|
public
interface
IApplicationObject {
void
Alert(
string
msg );
//
产生一条信息
void
ShowInStatusBar(
string
msg );
//
将指定的信息显示在状态栏
IDocumentObject QueryCurrentDocument();
//
获取当前使用的文档对象
IDocumentObject[] QueryDocuments();
//
获取所有的文档对象
//
设置事件处理器
void
SetDelegate( Delegates whichOne , EventHandler targer );
}
//
目前只需要这一个事件
public
enum
Delegates {
Delegate_ActiveDocumentChanged ,
}
|
|
///
///
编辑器对象必须实现这个接口
///
public
interface
IDocumentObject {
// 这些属性是 RichTextBox 控件的相应的属性映射
string
SelectionText {
get
;
set
; }
Color SelectionColor {
get
;
set
; }
Font SelectionFont {
get
;
set
; }
int
SelectionStart {
get
;
set
; }
int
SelectionLength {
get
;
set
; }
string
SelectionRTF {
get
;
set
; }
bool
HasChanges {
get
; }
void
Select(
int
start ,
int
length );
void
AppendText(
string
str );
void
SaveFile(
string
fileName );
void
SaveFile();
void
OpenFile(
string
fileName );
void
CloseFile();
}
|
|
///
///
本程序的插件必须实现这个接口
///
public
interface
IPlugin {
ConnectionResult Connect( IApplicationObject app );
void
OnDestory();
void
OnLoad();
void
Run();
}
///
///
表示插件与主程序连接的结果
///
public
enum
ConnectionResult {
Connection_Success ,
Connection_Failed
}
|
|
///
///
用来指定一个插件的相关信息
///
public
class
PluginInfoAttribute : System.Attribute
{
///
///
Deprecated. Do not use.
///
public
PluginInfoAttribute() {}
public
PluginInfoAttribute(
string
name ,
string
version ,
string
author ,
string
webpage ,
bool
loadWhenStart ) {
// 细节已略去
}
public
string
Name {
get
{
return
_Name; } }
public
string
Version {
get
{
return
_Version; } }
public
string
Author {
get
{
return
_Author; } }
public
string
Webpage {
get
{
return
_Webpage; } }
public
bool
LoadWhenStart {
get
{
return
_LoadWhenStart; } }
///
///
用来存储一些有用的信息
///
public
object
Tag {
get
{
return
_Tag; }
set
{ _Tag =
value
; }
}
///
///
用来存储序号
///
public
int
Index {
get
{
return
_Index; }
set
{ _Index =
value
; }
}
private
string
_Name = "";
private
string
_Version = "";
private
string
_Author = "";
private
string
_Webpage = "";
private
object
_Tag =
null
;
private int
_Index = 0;
//
暂时不会用
private
bool
_LoadWhenStart =
true
;
}
|
|
///
///
My Pluging 1( Just for test )
///
[
PluginInfo(
"My Pluging 1( Just for test )" ,
"1.0" ,
"Jack H Hansen" ,
"http://blog.csdn.net/matrix2003b" ,
true
)
]
public class
MyPlugin1 : IPlugin {
public
MyPlugin1() { }
#region
IPlugin
成员
// 细节已略去
#endregion
private
IApplicationObject _App;
private
IDocumentObject _CurDoc;
}
|
|
private
bool
IsValidPlugin( Type t ) {
bool
ret =
false
;
Type[] interfaces = t.GetInterfaces();
foreach
( Type theInterface
in
interfaces ) {
if
( theInterface.FullName == "CSPluginKernel.IPlugin" ) {
ret =
true
;
break
;
}
}
return
ret;
}
|
|
plugins.Add( pluginAssembly.CreateInstance( plugingType.FullName ) );
|
|
注:
[1]
巴比伦塔的失败
《人月神话》,
Frederick P. Brooks Jr.
第 7 章 为什么巴比伦塔会失败
[2] COM
有关 COM/COM+ 的详细技术细节请参见《 Mastering COM and COM+ 》 ,
Ash Rofail
, Yasser Shohoud.
|

5832




被折叠的 条评论
为什么被折叠?



