پلاگین چیست؟
پلاگین برنامه است که با اضافه شدن به برنامه ای قابلیتهایی به ان برنامه اضافه می کند.
حتما شما با flash player اشنا هستید. برنامه ای که با نصب آن مرورگر شما قابلیت پخش انیمیشن های فلش را پیدا می کند. این برنامه یک پلاگین برای نرم مرورگر شماست.
پلاگین در .net framework
برای نوشتن برنامه ای در دات نت که قابلیت پذیرش پلاگین باشد به سه لایه احتیاج دارد
1.لایه رابط
2.لایه برنامه
3.لایه پلاگین
حالا بریم سروقت پروژه و هریک از سه لایه بالا را با تفصیل توضیح دهیم.
پروژه
یک برنامه ساده می خواهیم ایجاد کنیم که قابلیت پذیرش پلاگین را داشته باشد. این برنامه حاوی یک فرم است که روی ان دو عدد textbox است و می خواهیم پلاگین بنویسیم که به کنترلهای textbox روی فرم اصلی دسترسی پیدا کند و حاصلضرب دو عدد داخل textbox را بدست آورد و منویی هم به من فرم اصلی اضافه کند.
حالا یک solution در vs ایجاد کنید و یک پروژه جدید از نوع class library به نام IPlugin به آن اضافه کنید تا اولین لایه برنامه را ایجاد کنیم.
لایه رابط
حالا یک code file به پروژه اضافه کرده و با توجه به زبان یکی از کدهایه زیر را در ان قرار دهید.
با زبان وی بی


کد:

کد PHP:
Public Interface IPlugin

    Property Name
() As String

    Sub About
()
    
Sub DisplayPlugForm()
    
Sub GetMessage(ByVal msg As String)

    
Event SendMessage(ByVal msg As StringByVal IPlugin As IPlugin)
    
Property menu() As Windows.Forms.ToolStripItemCollection

End 
Interface 
با زبان سی شارپ
کد:
کد:
کد PHP:
namespace SDK 
public 
delegate void EventHandler(string msgIPlugin IPlugin);
public interface 
IPlugin 
{
    
string name();
    
void About();
    
void DisplayPlugForm();
    
void GetMessage(string msg);
    
event EventHandler SendMessage;
    
System.Windows.Forms.ToolStripItemCollection menu();

}

خوب interface بالا متدها و رویداها و خاصیتهایی که باید در هر پلاگین باشد را توصیف می کند.
خاصیت name این خاصیت حاوی نام پلاگین است.
خاصیت menu این خاصیت حاوی منوهایی است که می خواهیم به برنامه اصلی اضافه شود.
متد about این متد فرم توضیحات پلاگین را نمایش خواهد داد.
متد DisplayPlugForm فرم اصلی پلاگین را نمایش می دهد.
متد GetMessage این متد برای فرستادن پیغام از برنامه اصلی به پلاگین بکار می رود.
رویداد SendMessage این رویداد وقتی اجرا می شود که بخواهیم پیغامی را از پلاگین به برنامه اصلی بفرستیم .
خوب لایه اول تمام شد.
لایه برنامه
ابتدا یک پروژه جدید از نوع application به نام program به solution خود اضافه کنید و پروژه قبلی را به فهرست رفرنس های این پروژه اضافه کنید.
این قسمت برنامه شامل دو کلاس مهم است.
اولین کلاس IPlugin_Collection این کلاس همانطور که از نامش پیداست یک مجموعه است که ما تمام پلاگین هایه خودمان را در ان نگه می داریم کد این کلاس
وی بی
کد:
کد:

کد PHP:
Imports sdk

Public Class IPlugin_Collection
    Inherits CollectionBase

    
Public Property item(ByVal iIndex As Integer) As IPlugin
        Get
            
Return (InnerList.Item(iIndex))
        
End Get
        Set
(ByVal Value As IPlugin)
            
InnerList.Item(iIndex) = Value
        End Set
    End Property

    
Public Function add(ByVal iPluginObj As IPlugin) As Integer
        
Return InnerList.Add(iPluginObj)

    
End Function

    Public Function 
contains(ByVal iPluginObj As IPlugin) As Boolean
        
Return (InnerList.Contains(iPluginObj))
    
End Function

    Public Function 
indexOf(ByVal iPluginObj As IPlugin) As Integer
        
Return (InnerList.IndexOf(iPluginObj))
    
End Function

    Public 
Sub remove(ByVal iPluginObj As IPlugin)
        
Call InnerList.Remove(iPluginObj)
    
End Sub

   

End 
Class

با سی شارپ
کد
:
کد:

using System;
using System.Collections.Generic;
using System.Text;
using SDK;

namespace 
program
{
   public  class 
IPlugin_Collection System.Collections.CollectionBase
    
{
        public 
IPlugin  this[int index]
        {
            
get
            
{
                return (
IPlugin )this.InnerList[index];
            }
            
set
            
{
                
this.InnerList[index] = value;
            }
        }
       public 
int add(IPlugin iPluginObj
        {
            return 
this.InnerList.Add(iPluginObj);
            
        }
       public 
bool contains(IPlugin iPluginObj
        {
            return 
this.InnerList.Contains(iPluginObj);
        }
       public 
int indexOf(IPlugin iPluginObj
        {
            return 
this.InnerList.IndexOf(iPluginObj);
        }
       public 
void remove(IPlugin iPluginObj)
        {
            
this.InnerList.Remove(iPluginObj);
        }
        }

فکر نکنم نیازی به توضیح باشد.
کلاس بعدی کلاس plugin_manager است در این کلاس ما پلاگین ها را لود می کنیم.
ما برای لود پلاگین ها علاوه بر داشتن فایل dll انها باید نام کلاس اصلی این پلاگین ها که براساس انترفیس پروژه اول ما شکل گرفته اند را باید داشته باشیم.من در این برنامه اطلاعات پلاگین ها را در ریجیستری ذخیره کردم.که بعدا در این مورد بیشتر توضیح میدهیم حالا کد کلاس
وی بی
کد:
کد:

کد PHP:
Imports SDK
Public Class plugin_manager
    
Public cPicPlugins As New IPlugin_Collection()
    Public 
Event reciveMessage(ByVal msg As StringByVal IPlugin As IPlugin)

    Private 
Sub recive(ByVal msg As StringByVal IPlugin As IPlugin)
        
RaiseEvent reciveMessage(msgIPlugin)
    
End Sub
   

    
Public Sub load_plugin()
        
Dim rr1r2 As Microsoft.Win32.RegistryKey
        Dim s
(), s1pStrPathpStrType As String
        r 
Microsoft.Win32.Registry.LocalMachine
        r1 
r.OpenSubKey("SOFTWARE\my program\plug in"False)
        
r1.GetSubKeyNames
        
For Each s1 In s
            
Try
                
r2 r1.OpenSubKey(s1)
                
pStrPath r2.GetValue("path")
                
pStrType r2.GetValue("type")
            Catch 
ex As Exception
            End 
Try
            Try
                
Dim pObhHandle As Runtime.Remoting.ObjectHandle Activator.CreateInstanceFrom(pStrPathpStrType)
                
Dim pIpnPlugin As SDK.IPlugin CType(pObhHandle.UnwrapSDK.IPlugin)
                
Call cPicPlugins.add(pIpnPlugin)
                
AddHandler pIpnPlugin.SendMessageAddressOf recive
            
Catch ex As Exception
                MsgBox
(ex.ToString)
            
End Try
        
Next
    End Sub

End 
Class 
در سی شارپ
کد:
کد:
کد PHP:
namespace program
{
    
using SDK;
    public class 
plugin_manager
    
{
        public    
IPlugin_Collection cPicPlugins = new IPlugin_Collection();
        public 
event reciveMessageEventHandler reciveMessage;
        public 
delegate void reciveMessageEventHandler(string msgIPlugin IPlugin);

        private 
void recive(string msgIPlugin IPlugin)
        {
            if (
reciveMessage != null)
            {
                
reciveMessage(msgIPlugin);
            }
        }
       
        
        public 
void load_plugin()
    {
        
Microsoft.Win32.RegistryKey r;
        
Microsoft.Win32.RegistryKey r1;
        
Microsoft.Win32.RegistryKey r2;
        
string[] s;
        
        
string pStrPath=null ;
        
string pStrType=null ;
        
Microsoft.Win32.Registry.LocalMachine;
        
r1 r.OpenSubKey("SOFTWARE\\my program\\plug in"false);
        
r1.GetSubKeyNames();
        foreach (
string s1 in s)
        {
            try {
                
r2 r1.OpenSubKey(s1);
                
pStrPath = (string )r2.GetValue("path");
                
pStrType = (string)r2.GetValue("type");
            }
            catch (
Exception ex) {
            }
            try {
                
System.Runtime.Remoting.ObjectHandle pObhHandle Activator.CreateInstanceFrom(pStrPathpStrType);
                
SDK.IPlugin pIpnPlugin = (SDK.IPlugin)pObhHandle.Unwrap();
                
cPicPlugins.add(pIpnPlugin);
                
pIpnPlugin.SendMessage += recive;
            }
            catch (
Exception ex) {
                
System.Windows.Forms.MessageBox.Show(ex.ToString());
            }
        }
    }

    }


توضیحات کلاس
متد load_plugin از اسمش داد میزنه که رای لود پلاگین ها بکار می رود.در این تابع اطلاعات از ریجیستری خوانده شده و dll پلاگین ها لود می شود. لود این dll ها در این دو خط کد است.
وی بی
کد:
کد:

Dim pObhHandle As Runtime.Remoting.ObjectHandle = Activator.CreateInstanceFrom(pStrPath, pStrType)
Dim pIpnPlugin As SDK.IPlugin = CType(pObhHandle.Unwrap, SDK.IPlugin)

سی شارپ
کد:
کد:

کد PHP:
System.Runtime.Remoting.ObjectHandle pObhHandle Activator.CreateInstanceFrom(pStrPathpStrType);
                
SDK.IPlugin pIpnPlugin = (SDK.IPlugin)pObhHandle.Unwrap(); 
پس از لود انها را در مجوعه پلاگین قرار می دهیم.
cPicPlugins مجموعه پلاگین هایه ماست.
رویداد reciveMessage این رویداد واسطه ای بین رویداد sendmessage یک پلاگین و فرم اصلی برنامه است.
تابع recive هم این رویداد را فرا می خواند.
کدهای فرم اصلی
با وی بی
کد:
کد:
کد PHP:
Dim WithEvents p As New plugin_manager
    Dim plug 
As SDK.IPlugin
    Dim a 
As Integer

    
Private Sub p_reciveMessage(ByVal msg As StringByVal IPlugin As SDK.IPluginHandles p.reciveMessage
        
If msg "textbox1" Then
            p
.cPicPlugins.item(p.cPicPlugins.indexOf(IPlugin)).GetMessage(TextBox1.Text)
        ElseIf 
msg "textbox2" Then
            p
.cPicPlugins.item(p.cPicPlugins.indexOf(IPlugin)).GetMessage(TextBox2.Text)
        
End If
    
End Sub

    
Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgsHandles Button1.Click
        p
.load_plugin()
        For 
0 To p.cPicPlugins.Count 1
            plug 
p.cPicPlugins.item(a)
            If 
Not plug.menu Is Nothing Then
                Me
.MenuStrip1.Items.AddRange(p.cPicPlugins.item(a).menu)
            
End If
        
Next

    End Sub 
با سی شارپ
کد:
کد:

کد PHP:
namespace program
{
    public 
partial class Form1 Form
    
{
        
plugin_manager p;
        
SDK.IPlugin plug;
        
int a;
        public 
Form1()
        {
            
InitializeComponent();
            
= new plugin_manager();
            
p.reciveMessage += new plugin_manager.reciveMessageEventHandler(p_reciveMessage);
        }

        
void p_reciveMessage(string msgSDK.IPlugin IPlugin)
        {
            if (
msg == "textbox1") { p.cPicPlugins[p.cPicPlugins.indexOf(IPlugin)].GetMessage(TextBox1.Text); }
            if (
msg == "textbox2") { p.cPicPlugins[p.cPicPlugins.indexOf(IPlugin)].GetMessage(TextBox2.Text); }
            
        }
        
        private 
void Button1_Click(object senderEventArgs e)
        {
            
p.load_plugin();
            for (
0p.cPicPlugins.Counta++) {
                
plug p.cPicPlugins[a];
                if (
plug.menu() != null) { this.MenuStrip1.Items.AddRange(p.cPicPlugins[a].menu()); }
            }
        }
    }

تو ضیحات کد
متغییر ها که نیاز به توضیح ندارند اما دو تابع رویداد اولی تابع p_reciveMessage که وقتی اطلاعاتی از پلاگین ها می رسد اجرا می شود. در این تابع ما پس از کردن پیغام پاسخ مناسب را می فرستیم مثلا در اینجا یک پلاگین با فرستادن پیغام textbox1 ما برای ان مقدار text این کنترل را می فرستیم.
رویداد کلیک دکمه لود پلاگین ها با اجرا شدن این تابع پلاگین ها لود و منو های داخل ان در منو اصلی برنامه ادغام می شود.


لایه پلاگین
ابتدا یک پروژه از نوع application ایجاد کنید.سپس در قسمت خصوصیات پروژه نوع پروژه را از application به class library تغییر دهید چون باید خروجی ما حتما یک dll باشد.سپس پروژه اولون یعنی IPlugin را به رفرنس های برنامه اضافه کنید
این پروژه یک کلاس مهم بنام my_plugin دارد.این کلاس براساس Interface IPlugin که در پروژه اول نوشتیم ایجاد می شود.
کد وی بی
کد:
کد:

کد PHP:
Imports sdk

Public Class my_plugin
    
Implements IPlugin
    Dim WithEvents f 
As Form1
    
Public Sub New()
        
= New Form1
    End Sub
#Region "Private declarations"

    
Private Const IPlugin_name As String "my_plugin"

#End Region

#Region "Property interface"

    
Public Property Name() As String Implements IPlugin.Name
        Get
            
Return (IPlugin_name)
        
End Get
        Set
(ByVal value As String)

        
End Set
    End Property

    
Public Property menu() As Windows.Forms.ToolStripItemCollection Implements IPlugin.menu
        Get
            
Return (f.MenuStrip1.Items)
        
End Get
        Set
(ByVal value As Windows.Forms.ToolStripItemCollection)

        
End Set
    End Property
    Dim message 
As String
    
Public Sub GetMessage(ByVal msg As String) Implements IPlugin.GetMessage
        message 
msg
    End Sub

    Event SendMessage
(ByVal msg As StringByVal IPlugin As IPlugin) Implements IPlugin.SendMessage


    
Public Sub About() Implements IPlugin.About

        Dim f 
As New about
        f
.ShowDialog()
    
End Sub

    
Public Sub DisplayPlugForm() _
        
Implements IPlugin.DisplayPlugForm
        f
.Show()
    
End Sub

#End Region


    
Private Sub f_menu1_click() Handles f.menu1_click
        RaiseEvent SendMessage
("textbox1"Me)
        
f.Int(Message)
        
RaiseEvent SendMessage("textbox2"Me)
        
f.Int(Message)
    
End Sub
End 
Class 
کد سی شارپ
کد:
کد:

کد PHP:
using System;
using System.Collections.Generic;
using System.Text;
using SDK;
namespace 
my_plugin
{
    class 
my_plugin :IPlugin
    
{
        
#region IPlugin Members
        
const string IPlugin_name "my_plugin";
        
string message=null ;
        
Form1 f ;
        public 
string name()
        {
            return  
IPlugin_name;
        }

        public 
void About()
        {
            
about f = new about();
            
f.ShowDialog();
        }

        public 
void DisplayPlugForm()
        {
                        
f.Show();
        }

        public 
void GetMessage(string msg)
        {
            
message msg;
        }

        public 
event SDK.EventHandler SendMessage;

        public 
System.Windows.Forms.ToolStripItemCollection menu()
        {
            return 
f.menuStrip1.Items ;
        }

        
#endregion
        
public my_plugin() {
            
= new Form1();
            
f.menu1_click += new Form1.menu1_click_eventhandler(f_menu1_click);
        }

        
void f_menu1_click()
        {
            
SendMessage("textbox1"this);
            
f.Convert.ToInt32(message);
            
SendMessage("textbox2"this);
            
f.Convert.ToInt32(message);
        }
    }

توضیحات کد
خاصیت name و menu اولی نام پلاگین را بر می گرداند دومی هم menu فرم اصلی ]چون فرصت نداشتم منو با کد تعریف کنم یک منو داخل فرم گذاشتم بعد ایتم های ان را به عنوان منو می فرستم اما شما در برنامه هاتون این کار را نکنید[
تابع GetMessage هم اطلاعات در یافتی از برنامه اصلی را در متغییر رشته ای بنام message ذخیره می کند.
رویداد SendMessage فکر نکنم نیاز به توضیح داشته باشد.
تابع های About و DisplayPlugForm هم به ترتیب فرم های توضیحات برنامه و فرم اصلی را نمایش می دهد.
تابع رویداد f_menu1_click این هم وقتی اجرا می شود که منو روی فرم اصلی کلیک شود.
این تابع پبغامی را به برنامه اصلی فرستاده و از برنامه اصلی مقدار کنترل هلی تکس با کس را می کند و سپس این مقادبر را در متغییرهایی که در فرم اصلی تعریف کردیم ذخیره می کند.
می رسیم به کد فرم اصلی
با وی بی
کد:
کد:

کد PHP:
Public Class Form1
    
Public aAs Integer
    
Public Event menu1_click()
    Private 
Sub ضربToolStripMenuItem_Click(ByVal sender As System.ObjectByVal e As System.EventArgsHandles ضربToolStripMenuItem.Click
        RaiseEvent menu1_click
()
        
Me.Show()
        
Label1.Text "حاصلضرب اعداد شما برابر" + (b).ToString
    End Sub

    
Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgsHandles MyBase.Load
        Me
.MenuStrip1.Hide()
    
End Sub
End 
Class 
با سی شارپ
کد:
کد:

کد PHP:
namespace my_plugin
{
    public 
partial class Form1 Form
    
{
        public  
delegate void  menu1_click_eventhandler();
        public 
Form1()
        {
            
InitializeComponent();
        }
        
        public 
event menu1_click_eventhandler menu1_click;
        private 
void ضربToolStripMenuItem_Click(object senderEventArgs e)
        {
            
menu1_click();
            
this.Show();
            
this.label1.Text "حاصلضرب اعداد شما برابر" + (b).ToString();
        }
       public  
int ab;
        private 
void Form1_Load(object senderEventArgs e)
        {
            
this.menuStrip1.Hide();
        }
    }

توضیحات کد
دو متغییر a,b که قبلا توضیح دادم رویداد menu1_click هم که رویدادی است که با فشرده شدن منو فرا خوانده می شود و بقیه کدها هم فکر نکنم نیاز به توضیح باشد.
اجرای برنامه مثال
ابتدا شما فایل ریجیستری برنامه را با نام reg.reg را اجرا کنید تا کلید و مقادیر ریجیستری ایجاد شود و سپس برنامه را اجرا نمایید.