使用asp.net或vb.net或C#.net均可以实现插件的功能,插件的作用是对系统的后期未知扩展预留快速升级的空间!插件开发完成后将以DLL的形式发布到特定的文件夹中,例如主程序文件夹是D:\myApp\myApp.exe,我们可以在D:\myApp中定义文件夹D:\myApp\Plus目录来存放插件。
在程序中通过遍历该文件夹中的所有DLL检测符合预定接口的插件来实现动态装载相应的功能模块!
下面举例:
一、定义接口
新建解决方案用于生成此接口
1
Public
Class
IPlugin
2
Public
Interface
IPlugin
3
Property
MovementID()
As
Integer
4
Property
MovementName()
As
String
5
Property
ReTryMinute()
As
Integer
6
Property
ConnectionString()
As
String
7
Event
RaiseLog(
ByVal
log
As
String
)
8
Sub
Init()
9
End Interface
10
End Class
11
二、编写继承自该接口的自定义组件(将编译成DLL)
该操作您需要新建一个解决方案
1
Imports
System.Data
2
Imports
System.Data.SqlClient
3
Imports
System.Net
4
Imports
System.IO
5
Imports
na7Interface.IPlugin
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Public
Class recv
Class recv
8![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
Implements IPlugin '实现此接口
10![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
'构造属性变量
12
Private _MovementID As Integer = 27
13
Private _MovementName As String = "51麦克疯"
14
Private _SpanMinute As Integer = 30
15
Private _ConnectionString As String = ""
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
Private Fir As String = "活动:" + MovementName + "(" + MovementID.ToString + ")"
18![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
20
''' 返回内部处理的消息,实现接口中的RaiseLog事件。
21
''' </summary>
22
''' <param name="logText"></param>
23
''' <remarks></remarks>
24
Public Event RaiseMyEvent(ByVal logText As String) Implements IPlugin.RaiseLog
25![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
27
''' 调用此方法!
28
''' </summary>
29
''' <remarks></remarks>
30![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub Init()Sub Init() Implements IPlugin.Init '继承自接口的Init方法。
31
'这里放置数据抓取及相关的处理程序。
32
'实际应用中要根据您的程序何时调用Init决定,这不是必须的方法
33
ResultText("处理完成!")
34
End Sub
35![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Sub SaveSetups()Sub SaveSetups(ByVal savedate As String, ByVal UserID As String, ByVal WebId As String, ByVal Setups As String)
37
'定义该内部方法,这个方法不实现任何接口中的方法。因此只在本类内部实现。
38
Dim CmdText As String = ""
39
End Sub
40![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
42
''' 返回八位数字的日期格式
43
''' </summary>
44
''' <param name="dt"></param>
45
''' <returns></returns>
46
''' <remarks></remarks>
47![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Function ClongDate()Function ClongDate(ByVal dt As Date) As String '同上
48
Dim mm As String = dt.Month.ToString
49
If mm.Length = 1 Then mm = "0" + mm
50
Dim dd As String = dt.Day.ToString
51
If dd.Length = 1 Then dd = "0" + dd
52
Return dt.Year.ToString + "" + mm + dd
53
End Function
54![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Private Function ConvDate()Function ConvDate(ByVal dt As Long) As String '同上
56
Dim YY As String = Mid(dt.ToString, 1, 4)
57
Dim MM As String = Mid(dt.ToString, 5, 2)
58
Dim DD As String = Mid(dt.ToString, 7, 2)
59
Return YY + "-" + MM + "-" + DD + " 00:00:00"
60
End Function
61![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
62![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
63
''' 获得此组件处理的活动ID,该属性实现了接口IPlugin的MovementID属性。
64
''' </summary>
65
''' <value></value>
66
''' <returns></returns>
67
''' <remarks></remarks>
68![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property MovementID()Property MovementID() As Integer Implements IPlugin.MovementID
69
Get
70
Return _MovementID
71
End Get
72
Set(ByVal value As Integer)
73
_MovementID = value
74
End Set
75
End Property
76![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
77![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
78
''' 获得此组件的活动名称,同上
79
''' </summary>
80
''' <value></value>
81
''' <returns></returns>
82
''' <remarks></remarks>
83![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property MovementName()Property MovementName() As String Implements IPlugin.MovementName
84
Get
85
Return _MovementName
86
End Get
87
Set(ByVal value As String)
88
_MovementName = value
89
End Set
90
End Property
91![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
92![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/''' <summary>
93
''' 获得此组件定时调用的间隔分钟数,实现自定义属生ReTryMinute
94
''' </summary>
95
''' <value></value>
96
''' <returns></returns>
97
''' <remarks></remarks>
98![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property SpanMinute()Property SpanMinute() As Integer Implements IPlugin.ReTryMinute
99
Get
100
Return _SpanMinute
101
End Get
102
Set(ByVal value As Integer)
103
_SpanMinute = value
104
End Set
105
End Property
106![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
107![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Property ConnectionString()Property ConnectionString() As String Implements IPlugin.ConnectionString
108
Get
109
Return _ConnectionString
110
End Get
111
Set(ByVal value As String)
112
_ConnectionString = value
113
End Set
114
End Property
115![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
116![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub ResultText()Sub ResultText(ByVal txt As String)
117
'响应事件
118
RaiseEvent RaiseMyEvent(txt)
119
End Sub
120
End Class
121
三、在程序中调用定义的接口
注意:程序中定义接口编译生成的DLL必须使用同一个,否则如果不是使用相同的DLL,即使DLL的内容相同,同样也会产生错误。
ShowPlus.aspx.vb
Imports System.Data
Imports System.Data.SqlClient
Imports System.Reflection
Imports PlusFace.Face
Public Class ShowPlus
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
loadPlus()
End Sub
Private Sub loadPlus()
'遍历Plus目录下的dll文件
dllFileName.Items.Add(New ListItem("请选择接口插件", ""))
Dim DirPath As String = Server.MapPath("..\Interface")
If IO.Directory.Exists(DirPath) = False Then
IO.Directory.CreateDirectory(DirPath)
End If
Dim DirectoryPath() As String
DirectoryPath = System.IO.Directory.GetFileSystemEntries(DirPath)
For Each file As String In DirectoryPath
If System.IO.File.Exists(file) = True Then
'判断此文件扩展名是否为dll
If LCase(Strings.Right(file, 4)) = ".dll" Then
'获得此文件信息及此组件的入口类名称与
Dim Ref As Assembly
Ref = Assembly.LoadFrom(file)
For Each typeTmp As Type In Ref.GetTypes
If typeTmp.IsPublic = True Then
'下面判断是否实现了接口,如果是,则取当前类型为该类实现的类型
Dim TypeGet As Type = typeTmp.GetInterface("Plus")
If IsNothing(TypeGet) = False Then
Dim asmName As String = System.IO.Path.GetFileNameWithoutExtension(file)
Dim t As Type = Ref.GetType(typeTmp.FullName) '这是区分大小写的。
Dim Obj As Plus = CType(Activator.CreateInstance(t), Plus)
'下面加载插件
Dim FileName As String = Replace(file, Server.MapPath("..\Interface\"), "")
Response.Write(Obj.InterfaceName + "(" + FileName + ")")
Exit For
End If
End If
Next
End If
Else
End If
Next
End Sub
End Class
这里有本人2007年底花四个月时间写成的进销存系统,里面使用了插件机制生成的报表设计管理器,但没有使用到接口,而是预先定义好调用的方法。
http://www.newhua.com/soft/33504.htm
补充:回复里有朋友说到,无法卸载的问题,现在提供如何卸载的方法:
'获得此文件信息及此组件的入口类名称与
Dim Ref As Assembly
Ref = Assembly.LoadFrom(file)
'请将上面的代码,改为下面的代码,原理是将DLL文件以字节读取,这样即不存在DLL锁定的问题,因为就不需要释放。
Dim Ref As Assembly
Dim assemblyInfo() As Byte = IO.File.ReadAllBytes(FilePath)
Ref = Assembly.Load(assemblyInfo)