Eclipse Plug-in - Create extension point with extension for loading class dynamically

繼之前曾經提到,關於要載入的class假設是存在於另外一個plugin時,當下啟用應用時若沒有

勾選該plugin,如此一來catch exception時會繼續執行另一resource。在這邊將另外提到Eclipse

plugin的一個很重要的技術Extension point and extension,相信在.plugin內的頁籤您曾經設定過

Extensions,如之前有建立Preferences,當下會引入org.eclipse.ui.PreferencesPages 、

org.eclipse.core.runtime.preferences(Extension point),此時有相關的欄位需要我們填寫,

當下我們就是在擴充Preferences的功能(建立Extensions),因此執行應用後可以在Preferences

頁面內見到我們所定義的item!

相關概念如下圖:

圖片來源 - Vogella

也就是說,假設我將extensions內所定義的extension刪除掉,重新執行應用的話,Preferences內

就不會有我所定義的items了!

因此,在這裡我將要自行定義extension point,並且在另外一個plugin內建立extension,如此

一來一樣可以達到上一篇文章Eclipse Plug-in - Dynamic load other bundle's class所要的目的!

與該篇文章一樣,首先我們所開啟的頁面一樣是定義在plugin - com.bin.practice.ui內

而我們將在com.bin.practice.prefs內建立我們自訂的extension!

PS. 關於Extension point and extension的說明與定義可以參考Vogella

一、建立extension point

首先,我們在com.bin.practice.ui plugin內定義extension point,如下:


Extension Point ID and Extension Point Name好比註冊的識別碼,只要在同一個應用內的所有

plugin有使用到這個ID與Name所建立的extension! 之後都可以在程式內搜尋的到!

之後會自動跳到定義頁面,至Definition定義這個extension在建立時需要填寫那些欄位


在此定義一element - dialogDefine

欄位分別為 id, dialog_name, dialog_instance,在此除了前兩項為string type外

最後一項為一指定class

緊接著,在extension下建立一Sequence,並在其下建立剛剛所定義的element - dialogDefine

二、建立extension

extension point建立好之後,再來按照範例就是在plugin - com.bin.practice.prefs內建立之


再來請回到plugin - com.bin.practice.ui

至MyFormPage.java檔案內修改,關於這個檔案的程式可參照下面連結


這邊主要是修改tree addSelectionListener事件處理
tree.addSelectionListener(new SelectionListener(){
   @Override
   public void widgetSelected(SelectionEvent e) {
    // TODO Auto-generated method stub
    Tree element = (Tree) e.getSource();
    TreeItem[] t = element.getSelection();
    boolean opened = false;
    if(t != null && t.length > 0 && treeMap.containsKey(t[0].getText())){
     IExtensionRegistry registory = Platform.getExtensionRegistry();
     IExtensionPoint extensionPoint = registory.getExtensionPoint(Activator.PLUGIN_ID, "dialog");
     IConfigurationElement[] exts = extensionPoint.getConfigurationElements();
     for(IConfigurationElement ext : exts){
      try {
       opened = true;
       IDialog dialog = (IDialog) ext.createExecutableExtension("dialog_instance");
       dialog.setShell(formBody.getShell());
       dialog.setDialogItem(t[0].getText());
       dialog.open();
      } catch (CoreException e1) {
       // TODO Auto-generated catch block
       e1.printStackTrace();
      }
     }
     if(!opened){
        TitleAreaDialogTest dialog = new TitleAreaDialogTest(formBody.getShell(), t[0].getText());
        dialog.open();
     }
    }
   }

   @Override
   public void widgetDefaultSelected(SelectionEvent e) {
    // TODO Auto-generated method stub
   }
  });

請注意,registrory.getExtensionPoint()內需指定該extension point's

ID分成namespace => com.bin.practice.ui, simple identifier => dialog

再過來extensionPoint.getConfigurationElements()可以取得所有plugin有建立

extensions's elements。最後則是進行走訪來取得dialog_instance欄位的實體(class type)

接著,由於當您取得dialog_instance的實體時,程式並無法進行MessageDialogTest constructor

的呼叫來初始化! 以Eclipse Plug-in - Dynamic load other bundle's class的作法是如下取得實體

Object object = constr[0].newInstance(formBody.getShell(), t[0].getText()); 會帶入兩個參數進去


因此在這邊,我們將重新調整一下extension point的設定

首先建立一interface - IDialog.java
public interface IDialog {
 public void setShell(Shell shell);
 
 public void setDialogItem(String item);
 
 public int open();
}



再來是調整MessageDialogTest implements IDialog,並且override相關method
 @Override
 public int open(){
  return super.open();
 }

 @Override
 public void setShell(Shell shell) {
  // TODO Auto-generated method stub
  configureShell(shell);
 }

 @Override
 public void setDialogItem(String item) {
  // TODO Auto-generated method stub
  this.item = item;
 }

如此一來,執行下面這兩段code一樣可以達到初始化dialog的目的

dialog.setShell(formBody.getShell());
dialog.setDialogItem(t[0].getText());

而在取得dialog_instance的實體之後為什麼要轉型成IDialog?

因為如此一來才可以在沒有import MessageDialogTest不會有編譯錯誤

即假設今天在執行應用程式時沒有load com.bin.practice.prefs

這一種情境,程式將不會進入迴圈,opened => false,將執行的會是TitleAreaDialogTest

若有load com.bin.practice.prefs,程式將執行的會是MessageDialogTest

留言