SharpDevelop Addin(插件樹) 使用方法

SharpDevelop Addin(插件樹) 使用方法

  

   在經歷了N多次的迷茫和鬱悶後,今天終於明白了Addin這個東東怎麼使用。下面爲大家總結一下我研究的過程,希望大家看過我的文檔後,研究Addin這 個的東西不再這麼痛苦拉。而且可以更快的瞭解插件樹是怎麼運行的.好了,廢話不多說了,下面言歸正傳。

  

   Addin作爲SharpDevelop的核心組件,它提供了一種插件樹的機制來調用插件組成整個應用程序。我將把Addin的核心代碼從SharpDevelop中分離出來,然後作爲單獨的工程。

  

  全部的過程大概分這麼兩個部分:

  一、 從SharpDevelop中分離出Addin的代碼。

  二、 新建一個工程作爲調用插件樹的主程序。

  三、 新建一個插件以供程序調用。

  

  

  第一部分 分離出插件樹的核心代碼

  那麼首先來講講怎麼從SharpDevelop中導出Core工程到2003

  

  1. 我們要導出代碼首先就必須得到它的源碼,源碼可以在SharpDevelop的官方網站http://www.icsharpcode.com/OpenSource/SD/Download/ 中下載。

   2. 在下載完程序之後你可以在src/Main/Core 目錄下找到Core.prjx這個文件(此文件是SharpDevelop的工程文件),使用SharpDevelop打開此文件,這時候整個Core項 目就加載到SharpDevelop(Core爲整個SharpDevelop的核心工程,其中包括了插件樹、服務和屬性)。由於 SharpDevelop目前調試還沒有.net2003方便,所以我們把程序導出爲.Net2003的格式可以通過SharpDevelop的 “文件-》輸出工程——》選擇你要輸出的文件夾”來導出整個項目。

  3. 在輸出成功後用.Net2003加載剛纔輸出的解決方案然後編譯,這樣就可以在輸出目錄下的bin/debug目錄下找到 ICSharpCode.Core.dll這個文件了(此文件爲整個插件樹的核心組件,在後面的插件樹應用中全部都是引用的該組件)。

  4. 拷貝CoreKey.key這個文件到當前項目的目錄下。

  

  在經過上述三個步驟之後,整個Addin的代碼就從SharpDevelop代碼中分離出來了,是不是很簡單啊 ^_^。

  

  

  第二部分 建造一個新工程來利用插件樹的機制加載插件

  剛纔第一部分我們講解了如何分離出插件樹的核心代碼,此部分我將講解怎麼在應用程序中利用插件樹的機制來加載插件。

  

  1. 首先新建一個Windows應用程序AddinMain。

  2. 在剛纔新建的項目中刪除Form1然後添加一個類AddinsMain。

  3. 引用ICSharpCode.Core.dll組件(要得到此組件請看第一部分)。

  4. 當上述三個步驟完成後就開始編碼工作了,把下面的代碼Copy到AddinsMain類中。

  

  /********************************************************************

  * *

  * AddinsMain 運行插件樹的主程序 *

  * Vincen *

  * [email protected] *

  * 2004-11-28 *

  *********************************************************************/

  

  using System;

  using System.IO;

  using System.Diagnostics;

  using System.Reflection;

  using System.Drawing;

  using System.Collections;

  using System.Windows.Forms;

  using System.Resources;

  using System.Xml;

  using System.Threading;

  using System.Runtime.Remoting;

  using System.Security.Policy;

  

  //引用Core的命名空間

  using ICSharpCode.Core.Properties;

  using ICSharpCode.Core.AddIns.Codons;

  using ICSharpCode.Core.AddIns;

  using ICSharpCode.Core.Services;

  

  namespace AddinMain

  {

  /// <summary>

  /// AddinsMain 的摘要說明。

  /// </summary>

  public class AddinsMain

  {

  public AddinsMain()

  {

  //

  // TODO: 在此處添加構造函數邏輯

  //

  }

  

  /// <summary>

  /// 整個程序的入口點

  /// </summary>

  [STAThread()]

  public static void Main(string[] args)

  {

  //查找ADDIN的主目錄 默認情況下目錄爲當前目錄的../Addin/

  bool ignoreDefaultPath = false;

  string [] addInDirs = AddInSettingsHandler.GetAddInDirectories(out ignoreDefaultPath);

  AddInTreeSingleton.SetAddInDirectories(addInDirs, ignoreDefaultPath);

  

  ArrayList commands = null;

  try

  {

  //啓動默認的系統服務

  ServiceManager.Services.AddService(new Resource());

  

  //啓動後臺服務

  ServiceManager.Services.InitializeServicesSubsystem("/Workspace/Services");

  

  //在程序開始運行時首先加載的插件

  commands = AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Autostart").BuildChildItems(null);

  for (int i = 0; i < commands.Count; ++i)

  {

  ((ICommand)commands[i]).Run();

  }

  }

  catch (XmlException e)

  {

  MessageBox.Show("不能加載 XML :" + Environment.NewLine + e.Message);

  return;

  }

  catch (Exception e)

  {

  MessageBox.Show("加載出錯 :" + Environment.NewLine + e.ToString());

  return;

  }

  }

  }

  }

  下面爲大家解釋一下這段代碼的意思

  bool ignoreDefaultPath = false;

  string [] addInDirs = AddInSettingsHandler.GetAddInDirectories(out ignoreDefaultPath);

  AddInTreeSingleton.SetAddInDirectories(addInDirs, ignoreDefaultPath);

   此段代碼的意思是查找插件樹配置文件的路徑,它首先去調用AddInSettingsHandler.GetAddInDirectories() 方法(AddInSettingsHandler類在後面介紹)查找App.Config中的AddInDirectories這一項,如果在配置文件中 不存在這一項的話就返回空值。

  當調用AddInTreeSingleton.SetAddInDirectories(addInDirs, ignoreDefaultPath)方法時如果addInDirs爲空的話那麼插件樹配置文件的默認路徑爲 ../Addin/。

  

   ServiceManager.Services.AddService(new Resource());

  在找到插件樹配置文件路徑後首先要啓動一個默認的資源服務Resource(該服務爲系統的默認服務,必須啓動,否則程序將無法運行)。

  

  ServiceManager.Services.InitializeServicesSubsystem("/Workspace/Services");

  在啓動完程序的默認服務後就開始啓動自定義服務了。所有默認服務都是在配置文件的/Workspace/Services擴展點中。

  

  commands = AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Autostart").BuildChildItems(null);

  for (int i = 0; i < commands.Count; ++i)

  {

  ((ICommand)commands[i]).Run();

  }

  這段代碼就是程序啓動時加載前臺插件了,/Workspace/Autostart是系統自動運行命令的擴展點路徑,定義在這個路徑下的插件會在系統啓動的時候自動運行。

  

  5. 經過上述的步驟後插件就可以被加載了,不過這個時候程序還不能編譯,應爲我們的Resource類和AddInSettingsHandler類都沒有添加。

  下面我們首先添加AddInSettingsHandler類,該類爲插件樹控制類。

  代碼如下:

  /******************************************************************

   * *

   * AddInSettingsHandler 插件樹控制類 *

   * Vincen *

   * [email protected] *

   * 2004-11-28 *

   * *

  ********************************************************************/

  

  using System;

  using System.Configuration;

  using System.Collections;

  using System.Xml;

  

  

  namespace AddinMain

  {

   /// <summary>

   /// AddInSettingsHandler 的摘要說明。

   /// </summary>

   public class AddInSettingsHandler : System.Configuration.IConfigurationSectionHandler

   {

   public AddInSettingsHandler()

   {

   }

  

   public object Create(object parent, object configContext, System.Xml.XmlNode section)

   {

   ArrayList addInDirectories = new ArrayList();

   XmlNode attr = section.Attributes.GetNamedItem("ignoreDefaultPath");

   if (attr != null)

   {

   try

   {

   addInDirectories.Add(Convert.ToBoolean(attr.Value));

   }

   catch (InvalidCastException)

   {

   addInDirectories.Add(false);

   }

   }

   else

   {

   addInDirectories.Add(false);

   }

  

   XmlNodeList addInDirList = section.SelectNodes("AddInDirectory");

   foreach (XmlNode addInDir in addInDirList)

   {

   XmlNode path = addInDir.Attributes.GetNamedItem("path");

   if (path != null)

   {

   addInDirectories.Add(path.Value);

   }

   }

   return addInDirectories;

   }

  

   public static string[] GetAddInDirectories(out bool ignoreDefaultPath)

   {

    ArrayList addInDirs = System.Configuration.ConfigurationSettings.GetConfig("AddInDirectories") as ArrayList;

   if (addInDirs != null)

   {

   int count = addInDirs.Count;

   if (count <= 1)

   {

   ignoreDefaultPath = false;

   return null;

   }

   ignoreDefaultPath = (bool) addInDirs[0];

   string [] directories = new string[count-1];

   for (int i = 0; i < count - 1; i++)

   {

   directories[i] = addInDirs[i+1] as string;

   }

   return directories;

   }

   ignoreDefaultPath = false;

   return null;

   }

   }

  }

  

  添加完AddInSettingsHandler類後下面我們將添加資源服務類。

  首先在項目中添加一個AddInSettingsHandler類,然後COPY下列代碼到該類中,該類繼承了AbstractService類和實現了IResourceService接口。

  using System;

  using System.IO;

  using System.Windows.Forms;

  using System.Collections;

  using System.Threading;

  using System.Resources;

  using System.Drawing;

  using System.Diagnostics;

  using System.Reflection;

  using System.Xml;

  

  using ICSharpCode.Core.Properties;

  using ICSharpCode.Core.AddIns.Codons;

  using ICSharpCode.Core.AddIns;

  using ICSharpCode.Core.Services;

  

  namespace AddinMain

  {

   /// <summary>

   /// Resource 的摘要說明。

   /// </summary>

   public class Resource:AbstractService,IResourceService

   {

   public Resource()

   {

   //

   // TODO: 在此處添加構造函數邏輯

   //

   }

   #region IResourceService 成員

  

   public void RegisterAssembly(Assembly assembly)

   {

   // TODO: 添加 Resource.RegisterAssembly 實現

   }

  

   public string GetString(string name)

   {

   // TODO: 添加 Resource.GetString 實現

   return null;

   }

   #endregion

   }

  }

  在完成上述步驟後編譯程序,怎麼樣,是不是編譯成功了,嘻嘻!寫的好累啊,抽支菸回來!

  

  第三部分 新建一個插件

  

   在經過第一部分和第二部分之後下面將新建一個插件給AddMain調用。

  

  1.在剛纔的解決方案中添加一個類庫項目HelloWorld。

  2.在HelloWorld項目中新建一個窗體Form1。

  3.再新建一個類HelloWorldCommand,該類是作爲反射來調用HelloWorld窗體用的,代碼如下:

  using System;

  using System.Windows.Forms;

  using System.CodeDom.Compiler;

  using ICSharpCode.Core.AddIns;

  using ICSharpCode.Core.AddIns.Codons;

  

  namespace HelloWorld

  {

   /// <summary>

   /// HelloFormCommand 的摘要說明。

   /// </summary>

   public class HelloFormCommand:ICSharpCode.Core.AddIns.Codons.ICommand

   {

   public HelloFormCommand()

   {

   //

   // TODO: 在此處添加構造函數邏輯

   //

   }

   #region ICommand 成員

  

   public object Owner

   {

   get

   {

   // TODO: 添加 HelloFormCommand.Owner getter 實現

   return null;

   }

   set

   {

   // TODO: 添加 HelloFormCommand.Owner setter 實現

   }

   }

  

   public void Run()

   {

   // TODO: 添加 HelloFormCommand.Run 實現

   Application.Run(new Form1());

   }

  

   #endregion

   }

  }

  

  該類實現了ICSharpCode.Core.AddIns.Codons.ICommand接口。

  

  public void Run()

   {

   // TODO: 添加 HelloFormCommand.Run 實現

   Application.Run(new Form1());

   }

  

  這裏面最重要的就是Run方法了,在該方法中運行我們剛剛新建的Form1窗體。

  

  好了,到了這個時候我們只差最後100米的距離了就是插件樹的配置文件了。剛剛我們講過插件樹的配置文件默認路徑是../Addin/目錄下,那麼我們在該目錄下建立一個Hello. Addin文件,下面我們來講解下該文件的格式。

  <AddIn name = "AddinTreeView"

   author = "SimonLiu"

   copyright = "GPL"

   url = "http://www.icsharpcode.net"

   description = "Display AddinTree"

   version = "1.0.0">

  

   <Runtime>

   <Import assembly="../../../HelloWorld/bin/Debug/HelloWorld.dll"/>

   </Runtime>

   <Extension path = "/Workspace/Autostart">

   <Class id = "HelloWorld"

   class = "HelloWorld.HelloCommand"/>

   </Extension>

  </AddIn>

  

   在配置文件中,Runtime節指定了插件功能模塊所在的庫文件HelloWorld.dll的具體路徑,在Extension節中指定了擴展點路徑 /Workspace/Autostart(該路徑是指在程序運行時自動運行該插件),然後在Extension內指定了它的ID、Command類名。 保存此配置文件運行程序,是不是Form1出來了啊,呵呵 很簡單吧。

  

  總結

   經過我的“廢話連篇”想必各位都看煩了吧不過最後還是得羅嗦最後幾句,回顧整個過程,首先我們從SharpDevelop中分離出了Addin的核心代 碼,然後新建了一個主體工程利用Addin的機制來調用插件,最後我們新建了一個插件然後被調用,應爲SharpDevelop本身的代碼有些複雜,而且 我也只像分離出他的插件樹代碼來用,所以我精簡啦很多SharpDevelop的代碼。爲了方便起見我在這裏只是作了一個最簡單的示例程序,當然了大家可 以擴展這個示例程序。至於怎麼像SharpDevelop那樣把所有的插件掛接到一個主界面中,本人正在研究ing…,等研究出來後馬上會把研究的心得貼 上來,敬請期待

 

源文檔 <http://www.wangchao.net.cn/bbsdetail_54103.html>

 
發佈了3 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章