2012-09-21 84 views
0

我正在開發與科學儀器交互的.Net桌面應用程序。這個工具有很多種不同的形式,每種都有不同的特性,組件等,所以我想出了一個插件/模塊化架構,其中「模塊組件」包含所有必要的業務邏輯,用戶界面等與該硬件組件/功能進行交互。模塊化應用程序體系結構和Castle Windsor

目前我有一個解決方案,包含所有內容 - 「核心」應用程序項目,公共庫和「模塊」項目。我們的想法是,我們將整批安裝到客戶站點(而不是挑選他們需要的DLL),並使用包含所需模塊列表的配置文件「激活」相關模塊。

主應用程序項目使用CastleFindsor使用AssemblyFilter和自定義InstallerFactory加載模塊。它搜索每個模塊組件,查找實現IWindsorInstaller的裝飾有特定自定義屬性(具有包含模塊名稱的屬性)的類。只有當屬性的模塊名稱是請求的模塊名稱時,模塊的安裝程序纔會運行。這些安裝程序類負責使用Windsor(業務邏輯,視圖,視圖模型等)註冊該模塊所需的所有內容。

該解決方案在我的概念證明中工作正常,但是我可以看到兩個或更多個模塊在功能上非常相似的情況,因此需要共享通用代碼。假設我有項目「ModuleA」和「ModuleB」,他們的Windsor安裝人員在項目「ClassLibraryX」中註冊了相同的IFooService類。該應用程序將會崩潰,因爲IFooService已被重新編寫了兩次,而Windsor在構造函數請求時不會知道要解析哪一個。

處理這個問題的最佳方法是什麼?到目前爲止的想法: -

  • 找出一個特定的組件是否已經在Windsor註冊過。這感覺hacky(如果可能的話)
  • 使用名稱註冊組件,但我如何請求具有構造函數注入的命名實例?
  • 在每個模塊項目中創建一個新界面,如public interface IModuleAFooService : IFooService,並在整個項目中註冊/使用此界面(而不是IFooService)。

有什麼想法?

編輯:事實上,當Windsor嘗試分辨IFooService時,它不會倒下。當第二個模塊嘗試註冊相同的接口/具體實現時,它會崩潰!

回答

0

我看到它的方式,你有幾個選項。我認爲你有兩個主要問題。首先是你安裝共享接口兩次(或更多)。第二個是你可以有兩個不同版本的共享接口。

對於第一個問題,我會將共享接口分離出它們自己的程序集。在該程序集內部,我將有一個安裝程序,該安裝程序的範圍是該程序集。然後,您可以告訴Windsor安裝該共享組件,並知道如何連線。

對於第二個問題,你有兩個選擇(我看到它)。第一種選擇是讓您的共享組件向後兼容。第二個選擇是隔離你的運行時間(通過應用程序域或進程)。

+0

我也想過在「共享」程序集中安裝一個安裝程序,但我想這意味着要註冊這些共享組件,而不管是否有任何相關模塊已被「激活」。也許我只是從一座痣山上爬出一座山,而不必要的註冊(這在啓動時發生)的開銷很小。 –

+1

是的,我認爲可用組件的註冊幾乎沒有開銷。我會這樣想:您正在激活可以使用的核心組件,但是每個模塊都會在執行之前確保它處於活動狀態。 –

0

您是否可以不爲插件提供一些元數據,即給每個插件實現一個名稱屬性,windsor可以使用它來標識您想要的實現?

最近我還沒有使用過多的Castle,但我確信它確實有命名綁定/註冊的概念,所以您可以使用它作爲區分事物的一種方式,如果這不可行並且存在沒有其他的元數據可以使用,這會讓Windsor不那麼模糊,那麼我會選擇第三個選項。

剛剛看了一遍你的第二個選項(寫了上之後),這似乎是最好的選擇,我不記得確切的語法,但在大多數投資框架,你做這樣的事情:

var instance = Get<IMyInterface>("Named This"); 

會有負載但是您需要知道Windsor端的名稱,並在客戶端註冊並請求它。

+0

問題是我的應用程序可能會加載兩個插件,都需要相同的實現。每個插件是負責與溫莎註冊其依賴關係,並會不知道另外一個插件已經註冊了相同的執行,導致執行同樣被註冊兩次,導致溫莎摔倒。我知道你可以用不同的名字註冊相同的實現,但是當我使用構造函數注入時,我不知道你如何告訴Windsor你想要哪一個。 –

+0

OH我和你在一起,似乎有一個問題你忽略了,如果是這樣的話。如果你有2個插件都可以實現你需要的接口,可以說'ZipPlugin'和'RarPlugin',它們都共享一個你需要的實現,名爲CompressedFile:ICompressedFile,你可能沒有那個實現的版本,如果一個插件是版本1.0,另一個插件是2.1,那麼您可能會在其中一個可能兼容或不兼容的插件中使用更新版本,因此每個插件及其共享類的版本是您可能需要考慮的。 – Grofit

0

命名實例沒問題。您可以通過流暢配置中的DependsOn(Dependency.OnComponent("paramName", "serviceName"))方法來定義對具體命名服務的依賴關係。