5

我正在爲.NET 3.5應用程序(WinForms)設計一個簡單的插件框架。一個簡單的IoC容器,用於一個小插件系統

我們當前的應用程序需要開始支持在編譯時應用程序未知的不同「插件」/「擴展」的動態加載和「掛鉤」。

這些擴展將被「掛鉤」到應用程序的不同區域,例如作爲某些類的事件處理程序。

例如(簡化):

public class SomeSystem 
{ 
    public event Action<string> Completed; 

    public event Action<string> Failed; 

    public event Action<string> Stopped; 
} 

一種用途情況下,我想有是爲開發者能夠定義用於在插件組件這樣的事件處理程序,而無需應用程序知道這些。

據我所知,IoC容器允許在運行時動態發現對象並將它們註冊到容器中。

IoC容器是否也可以爲我完成各種事件?或者沒有這樣的框架,這項任務會更容易嗎?

如何設計如何爲這樣的任務集成IoC容器? (假設有多個擴展點,例如可用於註冊的不同事件)。

些問題,我發現自己問:

  1. 它是常見的插件本身提供註冊方法做登記?
  2. IoC是否應該註冊? (通常情況如何?)
  3. 如何在使用IoC容器時輕鬆定義擴展點?

回答

5

你可能想看看MEF。它允許你詢問所有的事情。它使用的術語(ComposableParts,Exports等)最初是令人困惑的,但它的使用非常簡單。

插件本身是否提供註冊方法來執行 註冊常見?

MEF使應用程序執行查找和註冊插件的工作。該插件只需要實現一個界面,指出「我是一個可以執行X的插件」。

IoC是否應該註冊? (通常如何做?

將消耗MEF插件的應用程序能夠指定它將如何加載插件。這可以通過搜索DLL目錄,讀取配置文件中的程序集名稱列表,檢查GAC - 任何事情。它是完全可擴展的(因爲您可以編寫自己的搜索類)

如何在使用IoC容器時容易定義擴展點 ?

MEF使用接口來定義的應用和插件之間的契約。

+0

MEF的,每個「部分」是一些接口的實現。這意味着對於每個可擴展性點,應該創建一個新的接口?例如,我有3個事件:OnA,OnB,OnC。我如何使插件能夠被MEF吸引到這些事件上? (沒有定義3個不同的接口)。 –

+0

我不明白這個問題 - 如果OnA,OnB和OnC在邏輯上是以這樣的方式關聯的,那麼他們可以合理地成爲單個接口的一部分,從而使它們成爲單一接口。如果它們沒有關聯,則使它們成爲單獨接口的一部分。或者我誤解了你的問題? –

+0

我的意思是,如果我想要動態註冊許多不同的事件,他們每個人都必須明確定義他們正在導入某個界面。這意味着我必須定義3個不同的接口(每個事件類型一個接口)。比方說,我有1個接口和3個事件導入這個接口的實現。所有3個事件將導入所有實現,這不是我所追求的。 –

0

此答案將特定於我的容器。

我們當前的應用程序需要開始支持應用程序在編譯時未知的不同「插件」/「擴展」的動態加載和「掛鉤」。

爲了能夠做到這一點,你必須確定你在你的將應用程序和所有的插件之間共享的類庫放置一些擴展接口。

舉例來說,如果你想你的應用程序能夠以東西添加到您可以創建以下界面應用程序菜單:

class ApplicationMenu 
{ 
    // The "File" menu 
    IMenuItem File { get; } 
} 

interface IMenuRegistrar 
{ 
    void Register(ApplicationMenu menu); 
} 

這意味着你的插件可以創建下面的類:

[Component] 
public class CoolPluginMenuRegistrar : IMenuRegistrar 
{ 
    public void Register(ApplicationMenu menu) 
    { 
     menu.File.Add("mnuMyPluginMenuName", "Load jokes"); 
    } 
} 

[Component]屬性用於我的容器,以便它可以發現並自動爲您註冊類。

所有你需要做的,登記所有擴展點像上面的一個是這樣的:

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var registrar = new ContainerRegistrar(); 
     registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll"); 
     var container = registrar.Build(); 

     // all extension points have been loaded. To load all menu extensions simply do something like: 

     var menu = GetMainMenu(); 
     foreach (var registrar in container.ResolveAll<IMenuRegistrar>()) 
     { 
      registrar.Register(menu); 
     } 
    } 
} 

這些擴展將是「上鉤」到不同的應用領域,如交鋒的事件處理程序某些類別。據我所知,IoC容器允許在運行時動態發現對象並將它們註冊到容器中。

是的。你得到了所有這一切。

IoC容器是否也可以爲我鎖定各種事件?或者沒有這樣的框架,這項任務會更容易嗎?

是的。我有一個內置的事件機制。將事件類(常規.NET類放入共享類圖書館)。簡約他們訂閱通過實現一個接口:

[Component] 
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted> 
{ 
    ISmtpClient _client; 
    IUserQueries _userQueries; 

    public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries) 
    { 
     _client = client; 
     _userQueries = userQueries; 
    } 

    public void Invoke(ReplyPosted e) 
    { 
     var user = _userQueries.Get(e.PosterId); 
     _client.Send(new MailMessage(user.Email, "bla bla")); 
    } 
} 

並公佈事件:

DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject")); 

事件可以通過任何插件只要進行處理,因爲它們:

  1. 可以訪問活動分類
  2. 已在容器中註冊([Component]或手動註冊)
  3. 實現ISubscriberOf<T>

它是常見的插件本身提供了一個註冊的方法做登記?

是的。通過在共享程序集中定義爲擴展點的不同接口。

IoC是否應該註冊? (通常情況如何?)

是的。如果容器提供它。

使用IoC容器時如何輕鬆定義擴展點?

您可以在這裏詳細瞭解它:http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container