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事件處理
  1. tree.addSelectionListener(new SelectionListener(){
  2. @Override
  3. public void widgetSelected(SelectionEvent e) {
  4. // TODO Auto-generated method stub
  5. Tree element = (Tree) e.getSource();
  6. TreeItem[] t = element.getSelection();
  7. boolean opened = false;
  8. if(t != null && t.length > 0 && treeMap.containsKey(t[0].getText())){
  9. IExtensionRegistry registory = Platform.getExtensionRegistry();
  10. IExtensionPoint extensionPoint = registory.getExtensionPoint(Activator.PLUGIN_ID, "dialog");
  11. IConfigurationElement[] exts = extensionPoint.getConfigurationElements();
  12. for(IConfigurationElement ext : exts){
  13. try {
  14. opened = true;
  15. IDialog dialog = (IDialog) ext.createExecutableExtension("dialog_instance");
  16. dialog.setShell(formBody.getShell());
  17. dialog.setDialogItem(t[0].getText());
  18. dialog.open();
  19. } catch (CoreException e1) {
  20. // TODO Auto-generated catch block
  21. e1.printStackTrace();
  22. }
  23. }
  24. if(!opened){
  25. TitleAreaDialogTest dialog = new TitleAreaDialogTest(formBody.getShell(), t[0].getText());
  26. dialog.open();
  27. }
  28. }
  29. }
  30. @Override
  31. public void widgetDefaultSelected(SelectionEvent e) {
  32. // TODO Auto-generated method stub
  33. }
  34. });

請注意,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
  1. public interface IDialog {
  2. public void setShell(Shell shell);
  3. public void setDialogItem(String item);
  4. public int open();
  5. }



再來是調整MessageDialogTest implements IDialog,並且override相關method
  1. @Override
  2. public int open(){
  3. return super.open();
  4. }
  5. @Override
  6. public void setShell(Shell shell) {
  7. // TODO Auto-generated method stub
  8. configureShell(shell);
  9. }
  10. @Override
  11. public void setDialogItem(String item) {
  12. // TODO Auto-generated method stub
  13. this.item = item;
  14. }

如此一來,執行下面這兩段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

留言