.Net实现程序的插件机制

使用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
  7 ExpandedBlockStart.gifContractedBlock.gif Public   Class recv Class recv
  8
  9    Implements IPlugin '实现此接口
 10
 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
 17    Private Fir As String = "活动:" + MovementName + "(" + MovementID.ToString + ")"
 18
 19ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 20    ''' 返回内部处理的消息,实现接口中的RaiseLog事件。
 21    ''' </summary>
 22    ''' <param name="logText"></param>
 23    ''' <remarks></remarks>

 24    Public Event RaiseMyEvent(ByVal logText As StringImplements IPlugin.RaiseLog
 25
 26ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 27    ''' 调用此方法!
 28    ''' </summary>
 29    ''' <remarks></remarks>

 30ExpandedSubBlockStart.gifContractedSubBlock.gif    Public Sub Init()Sub Init() Implements IPlugin.Init '继承自接口的Init方法。
 31        '这里放置数据抓取及相关的处理程序。
 32         '实际应用中要根据您的程序何时调用Init决定,这不是必须的方法
 33        ResultText("处理完成!")
 34    End Sub

 35
 36ExpandedSubBlockStart.gifContractedSubBlock.gif    Private Sub SaveSetups()Sub SaveSetups(ByVal savedate As StringByVal UserID As StringByVal WebId As StringByVal Setups As String)
 37        '定义该内部方法,这个方法不实现任何接口中的方法。因此只在本类内部实现。
 38        Dim CmdText As String = ""
 39    End Sub

 40
 41ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 42    ''' 返回八位数字的日期格式
 43    ''' </summary>
 44    ''' <param name="dt"></param>
 45    ''' <returns></returns>
 46    ''' <remarks></remarks>

 47ExpandedSubBlockStart.gifContractedSubBlock.gif    Private Function ClongDate()Function ClongDate(ByVal dt As DateAs 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
 55ExpandedSubBlockStart.gifContractedSubBlock.gif    Private Function ConvDate()Function ConvDate(ByVal dt As LongAs String '同上
 56        Dim YY As String = Mid(dt.ToString, 14)
 57        Dim MM As String = Mid(dt.ToString, 52)
 58        Dim DD As String = Mid(dt.ToString, 72)
 59        Return YY + "-" + MM + "-" + DD + " 00:00:00"
 60    End Function

 61
 62ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 63    ''' 获得此组件处理的活动ID,该属性实现了接口IPlugin的MovementID属性。
 64    ''' </summary>
 65    ''' <value></value>
 66    ''' <returns></returns>
 67    ''' <remarks></remarks>

 68ExpandedSubBlockStart.gifContractedSubBlock.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
 77ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 78    ''' 获得此组件的活动名称,同上
 79    ''' </summary>
 80    ''' <value></value>
 81    ''' <returns></returns>
 82    ''' <remarks></remarks>

 83ExpandedSubBlockStart.gifContractedSubBlock.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
 92ExpandedSubBlockStart.gifContractedSubBlock.gif    /**/''' <summary>
 93    ''' 获得此组件定时调用的间隔分钟数,实现自定义属生ReTryMinute
 94    ''' </summary>
 95    ''' <value></value>
 96    ''' <returns></returns>
 97    ''' <remarks></remarks>

 98ExpandedSubBlockStart.gifContractedSubBlock.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
107ExpandedSubBlockStart.gifContractedSubBlock.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
116ExpandedSubBlockStart.gifContractedSubBlock.gif    Public Sub ResultText()Sub ResultText(ByVal txt As String)
117        '响应事件
118        RaiseEvent RaiseMyEvent(txt)
119    End Sub

120End Class

121

 

三、在程序中调用定义的接口
     注意:程序中定义接口编译生成的DLL必须使用同一个,否则如果不是使用相同的DLL,即使DLL的内容相同,同样也会产生错误。

ContractedBlock.gif ExpandedBlockStart.gif 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 ObjectByVal 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)

转载于:https://www.cnblogs.com/soleds/archive/2009/05/03/1448262.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值