程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 閒談可插拔式應用程序的開發

閒談可插拔式應用程序的開發

編輯:關於.NET

很多軟件都是可插拔的,最知名的便是微軟的Windows操作系統。你可以在 Windows操作系統上安裝QQ,也可卸掉QQ,這便是可插拔。這裡不談 Windows的 實現,因為太過復雜。本文就談談管理軟件的可插拔的實現。相對Windows操作 系統,QQ就是它的一個插件。所以可以簡單的將開發可插拔的軟件分為兩個部分 。一個是主應用程序的開發,一個是插件的開發。

比Windows小的,常見的可插拔的軟件是MSN。MSN主應用程序由MS開發,還存 在一些MSN插件開發商,國內好像也有不少,這些插件開發商通過在插件中植入 廣告獲取利潤。MS不可能提高源代碼給這些開發商,那麼MSN的主應用程序和MSN 的插件是如何銜接起來的呢。我想應該是MS提供了一些接口和方法供開發商使用 ,估計有個api之類的東西,所以開發可插拔的應用系統分為三個部分。

1、主應用程序的開發

2、公用接口的開發

3、插件的開發

了解了這些以後,下面通過一個實例來說明。這個實例的原則是可擴展性強 ,能向下兼用。

業務需求是:老系統每當逢年過節的時候,會通過郵件給用戶發送一些祝福 的郵件。現在流行手機和MSN(QQ沒有借口)之後,客戶希望系統能通過手機短信 和MSN的消息給用戶送去祝福。現在我們需要開發手機短信和MSN留言兩個插件, 然後將它們安裝到系統中去。

實現:

為了簡單起見,這裡使用控制台應用程序,如果你有興趣,可以修改成 asp.net或者Windows Form的。

定義兩個接口:

public interface IPluginHost
{
   void AddMenuItem(string name, MenuItemClickedHandler  clickHandler);
   void RegisterComponent<T>(T component) where T :  class;
   void MailNotice(string messaage);
}
public delegate void MenuItemClickedHandler(string  name);

這個接口是主應用程序繼承的,現在只有MailNotice功能,  AddMenuItem是供插件調用的方法,創建一個菜單。RegisterComponent是插件向 主應用程序提供一些方法。

public interface IPlugin
{
   void Initialize(IPluginHost pluginHost);
   void DoSomething();
}

上面是插件的接口。

在主應用程序中有一個加載插件的地方。這裡的插件是dll,所以我通過反射 去加載這些dll。

public void LoadPlugin()
{
   foreach (string fileName in Directory.GetFiles (Directory.GetCurrentDirectory() + "\\" + "Plugins", "*.dll"))
   {
     Assembly assembly = Assembly.LoadFile(fileName);
     foreach (Type pluginType in assembly.GetTypes())
     {
       if (!pluginType.IsPublic || pluginType.IsAbstract  || pluginType.IsInterface)
         continue;
       Type concreteType = pluginType.GetInterface(typeof (IPlugin).FullName, true);

       if (concreteType != null)
       {
         IPlugin plugin = (IPlugin) Activator.CreateInstance(pluginType);
         plugin.Initialize(this);
         pluginList.Add(plugin);
         break;
       }
     }
   }
}

主應用程序執行的代碼如下:

void Start()
{
   //郵件發送祝福
   MailNotice("中秋快樂");
   //加載插件
   LoadPlugin();
   //運行插件
   if (pluginList.Count > 0)
   {
     foreach (IPlugin plugin in pluginList)
     {
       plugin.DoSomething();
     }
   }

   Console.ReadLine();
}

運行結果如下:

開發兩個插件,都繼承IPlugin。

手機短信通知插件:

public class PluginA : IPlugin
{

   public void Initialize(IPluginHost pluginHost)
   {
     IPluginHost myApplication = (IPluginHost)pluginHost;
     myApplication.AddMenuItem("Click me", OnClick);

   }
   private void OnClick(string name)
   {
     Console.WriteLine("Omg! You clicked me!");
   }

   public void DoSomething()
   {
     Console.WriteLine("手機短信通知:中秋快樂");
   }

}

MSN通知插件:

public class PluginB : IPlugin
{

   public void Initialize(IPluginHost pluginHost)
   {
     IPluginHost myApplication = (IPluginHost)pluginHost;
     myApplication.AddMenuItem("Click me", OnClick);

   }
   private void OnClick(string name)
   {
     Console.WriteLine("Omg! You clicked me!");
   }

   public void DoSomething()
   {
     Console.WriteLine("MSN信息通知:中秋快樂");
   }

}

插件的目錄如下圖:

運行效果:

擴展性和兼容性:

如果我想在主應用程序中添加一個ShowMessageBox方法。而且這個方法供插 件調用。考慮到版本的兼容性,公開的接口是不能修改的。比如:將主應用程序 的接口修改成:

public interface IPluginHost
{
   void AddMenuItem(string name, MenuItemClickedHandler  clickHandler);
   void RegisterComponent<T>(T component) where T :  class;
   T GetComponent<T>() where T : class;
   void MailNotice(string messaage);
   void ShowMessageBox(string message);
}

那麼如何實現呢,很簡單,使用依賴注入的方式。添加下面接口:

public interface IMessageBoxHost
{
   void ShowMessageBox(string message);
}

通過主應用程序的構造函數,將MessageBoxHost對下崗注入到主應用程序, 在通過插件的構造函數,將其注入插件之中。

主應用程序的構造函數:

public Program(IMessageBoxHost messageBoxHostInstance)
{
   this.messageBoxHostInstance = messageBoxHostInstance;
}

插件構造函數:

public PluginA(IMessageBoxHost messageBoxHost)
{
   this.messageBoxHost = messageBoxHost;
}

修改實例化插件的代碼:

IPlugin plugin = (IPlugin)Activator.CreateInstance (pluginType, new object[] { messageBoxHostInstance });

這樣我們對版本兼容有了保障。

總結:本文閒談了可插拔應用程序的開發原理,文章的後面提供了插件和應 用程序之間版本兼容的一種方案。有討論才有進步,歡迎各位留言。

參考代碼:http://files.cnblogs.com/zhuqil/Plugin.rar

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved