細談軟件插件式開發

          軟件行業競爭激烈,程序員寫了軟件還不行,老闆硬要給軟件程序添加插件。 java

        談起程序插件,不少軟件都用到插件,插件腳本語言,好比輸入法擴展插件lua,googl瀏覽器插件JavaScript。甚至連全部動態網站都離不開插件,插件,插件,即插即用。主要是知足用戶的需求。 程序員

        

什麼是插件式編程?

  提起插件式,咱們首先想到的是firefox, 用過firefox的人都知道它是一個插件式程序。當一個功能須要,徹底能夠從網上下載一個插件後,重啓後,就能使用。這個功能給咱們帶來許多的方便之處,這就是插件式程序的好處。 編程

  插件的本質在於不修改程序主體(平臺)的狀況下對軟件功能進行拓展與增強,當插件的接口公開後,任何公司或我的均可以製做本身的插件來解決一些操做上的不便或增長新功能,也就是真正意義上實現「即插即用」軟件開發。 c#

  平臺+插件軟件結構是將一個待開發的目標軟件分爲兩部分,一部分爲軟件的主體或框架,可定義爲平臺,這是預先編譯後的程序。另外一部分爲功能或補充模塊,可定義爲插件。這個就是後來要進行安裝的插件程序。 瀏覽器

  假設你的程序已經部署在用戶的計算機上,而且可以正常運行了。可是有一天,用戶打來電話——他們須要增長新的功能。肯定了用戶的需求後,你居然發現原有的軟件架構已經沒法勝任新增任務的需求——你須要從新設計這個應用了!但問題是,就算你又用了一個開發週期完成了用戶須要的應用,切不能保證用戶的需求不會再次變動。也就是說,需求蔓延的可能性依然存在。所以,這種狀況下插件架構更能顯示出它的優越性。 架構

  

  能夠這麼說,用它能夠帶來方便的地方,並且開發它,也很簡單。並且這樣的主程序根本就不須要改動。須要插件時,拿來就能用,插件更新時,也只需更新這個插件便可。 框架

      而net平臺與Java平臺都能擴展軟件插件。 eclipse

      現細談各平臺編程語言如何添加插件。 編程語言

    談談我學習java語言,用Java開發IDE插件 編輯器

我一直不知道有插件開發這樣一種技術路徑,本想着這開發工具都給你備好了,直接用不就好了。可是總有些IT工廠,爲了要節約成本,開發本身的開發工具,可是又要節省時間,總不能一切都本身來。畢竟開發一個eclipse也要很長時間的。所以,插件開發出如今歷史舞臺。

  首先要了解插件開發,就得從SWT/JFACE提及了。SWT是一種開源的界面開發框架,之前學java的時候,老是用一些panel,就相似這個。JFace又是一種基於SWT的UI不見的API。Eclipse就是用這個開發出來的,它提供了Eclipse強大的擴展性,所以可讓用戶任意的插入本身想要的插件,開發本身的IDE。

   如何實現,let's start


    

首先認識一下Eclipse,這個你們應該很熟了!

  1 紅色部分是咱們的工具欄

  2 藍色部分是視圖

  3 黃色部分是編輯器

  一般咱們使用編輯器,進行代碼操做,或者業務操做。在視圖,進行一些資源的查看等。紅色引入一些經常使用的功能,輔助咱們的操做。

咱們先作一個簡單的工具欄的控件,瞭解一下eclipse的插件開發流程!

首先,新建一個插件工程

   給eclipse項目建立好的名稱。


首先,寫入本身的插件名字。

  source folder 是插件的代碼路徑。

  output folder是插件輸出的目標路徑。

  下面是開發插件的eclipse的版本。

next,如何設置。


ID 是插件的標識

version 是插件的版本

Name是插件的名字

Provider是開發者的信息

 

下面的Activator,是插件的激活類,用來管理插件的生命週期。

 

最後是選擇是否開發RCP,富客戶端應用,暫且不用,選否OK啦。

使用插件模塊,建立一個插件工具。


next,按鈕信息設置。


默認會生成類的名字,路徑(包名),以及工具欄按鈕出發的消息提示。


  點擊finish,完成插件的建立。

插件完成,生成

導入了插件所須要用到的jar包

 導入了插件依賴的庫

 源文件

 插件按鈕圖片

插件的配置信息


  MANIFEST.MF 插件的捆綁信息

複製代碼
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: 個人插件 Bundle-SymbolicName: com.test.myplugin; singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: com.test.myplugin.Activator Bundle-Vendor: xingoo Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime Bundle-ActivationPolicy: lazy
複製代碼


  Name 是咱們以前設置的插件名字

  SymblicName 是咱們插件的包名

  version 是插件的版本

  Activator 是插件的激活類

  Vendor 是插件開發者的信息

  Bundle 是插件以來的庫

  這些信息都對應着插件的overview頁面的信息。

  

  plugin.xml 插件的詳細設置文檔,包含插件的擴展點信息,以及插件本身的信息

複製代碼
代碼以下:


<?xml version="1.0" encoding="UTF-8"?> 
<?eclipse version="3.
4"?> <plugin> <extension 
point="org.eclipse.ui.actionSets"> <actionSet 
label="Sample Action Set" 
visible="true" id="com.test.myplugin.actionSet">
<menu label="Sample &amp;Menu" id="sampleMenu"> 
<separator name="sampleGroup"> </separator> </menu> <action label="&amp;Sample Action" icon="icons/sample.gif" clas
s="com.test.myplugin.actions.SampleAction" 
tooltip="Hello, 
Eclipse world" menubarPath="sampleMenu/sampleGroup"
 toolbarPath="sampleGroup"
 id="com.test.myplugin.actions.SampleAction"> 
</action> </actionSet> </extension> </plugin>
複製代碼


  <plugin>元素清單的主體

  <extension>插件的功能擴展,裏面包括 point 擴展點的標識、id 擴展實例的標識、name 提供的用戶的名稱等等


  build.properties 構建的元素列表

複製代碼
source.. = src/ output.. = bin/ bin.includes = plugin.xml,\ META-INF/,\ .,\ icons/
複製代碼

  裏面包括插件的源文件目錄,生成文件目錄,還有一些配置信息的引入。


  提供的插件類Activator.java


複製代碼
 1 package com.test.myplugin; 
 2 
 3 import org.eclipse.jface.resource.ImageDescriptor; 
 4 import org.eclipse.ui.plugin.AbstractUIPlugin; 
 5 import org.osgi.framework.BundleContext;  
6  
7 /**  
8  * The activator class controls the plug-in life cycle  
9 */ 
10 public class Activator extends AbstractUIPlugin {
 11 
12 // The plug-in ID 
13 public static final String PLUGIN_ID = "com.test.myplugin"
14 
15 // The shared instance 
16 private static Activator plugin;
 17 
18 /**
19  * The constructor
 20 */ 
21 public Activator() { 
22 
23 
24 /* 
25  * (non-Javadoc) 
26  * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) 
27 */
28 public void start(BundleContext context) throws Exception {
 29 super.start(context);
 30 plugin = this;
 31 
32 
33 /*
34  * (non-Javadoc)
 35  * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) 
36 */ 
37 public void stop(BundleContext context) throws Exception { 
38 plugin = null
39 super.stop(context);
 40 
41 
42 /** 
43  * Returns the shared instance 
44 
45  * @return the shared instance
 46 */ 
47 public static Activator getDefault() { 
48 return plugin;
 49 
50 
51 /** 
52  * Returns an image descriptor for the image file at the given 
53  * plug-in relative path 
54 
55  * @param path the path 
56  * @return the image descriptor 
57 */
58 public static ImageDescriptor getImageDescriptor(String path) {
 59 return imageDescriptorFromPlugin(PLUGIN_ID, path); 
60 
61 }
複製代碼

  start()和stop()分別用於插件開始與中止調用的函數。

運行插件圖;

啓動方式1 直接在overview界面點擊;

   啓動方式2 也能夠點擊運行或者DEBUG按鈕,運行方式選擇Eclipse Application。

  

  點擊啓動後,會爲咱們從新開啓一個Eclipse,這個Eclipse就是帶有咱們建立的插件的新Eclipse。啓動效果以下:

插件完成。

net平臺,談談c#應用程序開發。

如何開發

從程序開發這角度,通常是先開發主程序,決定哪些功能由主程序來完成,而後再創建接口,申明接口的內容,這些內容決定着插件功能的擴展及方向的。這些都是有主程序開發者預先準備好的。插件開發者,從主程序開發者那裏獲得接口的內容,並書寫繼承這些接口的類,來完成具體的功能。

  下面來寫個例子,這個例子沒實際意義,純屬學習思想。例子是網上的通過本身改造的,發現別人某些地方不合理。

  首先,新建一個類庫,裏面定義接口,這裏定義兩個方法,一個有返回值的,一個無返回值的。

代碼以下:

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

namespace IMsg
{
///<summary>
/// 這是插件必須實現的接口,也是主程序與插件通訊的惟一接口
/// 換句話說,主程序只認識插件裏的這些方法
///</summary>
publicinterface IMsgPlug
{
  void OnShowDlg();
  string OnShowInfo();
}
}

將上面的類庫生成IMsg.dll, 新建一個類庫MYPlugin1,添加剛出的引用,分別新建兩個類來實現IMsg中定義的接口。

using  System;
using  System.Collections.Generic;
using  System.Text;
using  IMsg;
namespace  MYPlugin1
{
public class  myConsole : IMsgPlug
{
#region  IMsgPlug 成員
public void  OnShowDlg()
{
Console.WriteLine(
" 控制檯調用插件的OnShowDlg方法 " );
}
public string  OnShowInfo()
{
return " myConsole " ;
}
#endregion
}
}

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Windows.Forms;
using  IMsg;
namespace  MYPlugin1
{
public class  MYDlg:Form,IMsgPlug
{
#region  IMsgPlug 成員

public void  OnShowDlg()
{
this .Text  = " 插件子窗體 " ;
this .ShowDialog(); // 調用Form的ShowDialog,顯示窗體
}
public string  OnShowInfo()
{
return " MyDlg " ;
}
#endregion
}
}

  將上面的都生成dll, 生成目錄能夠設置爲新建exe工程的bin目錄plugins文件夾下。Plugins文件夾是新建的,專門存放插件的。 新建一個 WinForm項目來使用剛纔的插件.

圖:

代碼以下:

using System;

using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Text;
using  System.Windows.Forms;

using  System.Collections;
using  System.IO;
using  System.Reflection;
namespace  MsgBoxMain
{
public partial class  FormMain : Form
{

/// <summary>
///  存放插件的集合
/// </summary>
private  ArrayList plugins  = new  ArrayList();
public  FormMain()
{
InitializeComponent();
}

/// <summary>
///  載入全部插件
/// </summary>
private void  LoadAllPlugs()
{
// 獲取插件目錄(plugins)下全部文件
string [] files  =  Directory.GetFiles(Application.StartupPath  + @" \plugsins " );
foreach  ( string  file  in  files)
{
if  (file.ToUpper().EndsWith( " .DLL " ))
{
try
{
// 載入dll
Assembly ab  =  Assembly.LoadFrom(file);
Type[] types 
=  ab.GetTypes();
foreach  (Type t  in  types)
{
// 若是某些類實現了預約義的IMsg.IMsgPlug接口,則認爲該類適配與主程序(是主程序的插件)
if  (t.GetInterface( " IMsgPlug " ) != null )
{
plugins.Add(ab.CreateInstance(t.FullName));
listBox1.Items.Add(t.FullName);
}
}
}
catch  (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

private void  btnLoadPlug_Click( object  sender, EventArgs e)
{
LoadAllPlugs();
}

// 調用插件的方法
private void  btnExecute_Click( object  sender, EventArgs e)
{
if  ( this .listBox1.SelectedIndex  == - 1 return ;
object  selObj  = this .plugins[ this .listBox1.SelectedIndex];
Type t 
=  selObj.GetType();
MethodInfo OnShowDlg 
=  t.GetMethod( " OnShowDlg " );
MethodInfo OnShowInfo 
=  t.GetMethod( " OnShowInfo " );

OnShowDlg.Invoke(selObj, 
null );
object  returnValue  =  OnShowInfo.Invoke(selObj,  null );
this .lblMsg.Text  =  returnValue.ToString();

}
}
}

  運行結果:圖:

OK,大功告成。

        最後,感謝上帝!

阿們!

相關文章
相關標籤/搜索