2015-06-28 57 views
24

在我的Asp.Net MVC應用程序中,我有一些視圖文件(.cshtml),它引用了將在運行時加載的外部庫。所以在應用程序啓動後,我通過Assembly.Load加載程序集,並通過我自己的自定義ControllerFactory註冊了控制器,並且每件事都可以。如何在運行時在mvc中引用程序集

但是,在具有所述動態加載組件的引用的一些看法,投:

編譯器錯誤消息:CS0234:類型或命名空間名稱MyDynamicNamespace'不命名空間中存在「MyApp的」 (您是否缺少裝配參考?)

異常,它告訴剃鬚刀編譯器無法解析相關裝配。

我的問題是,有沒有辦法在運行時註冊程序集,以便剃鬚刀編譯器可以訪問它並解決它?

注意,我不能用BuildManager.AddReferencedAssembly的方法,因爲我的裝配有應用程序啓動後加載,並且BuildManager不支持它。

+1

我不清楚爲什麼你的要求是程序集啓動後必須加載程序集?這對於外部庫來說不是一個正常的用例。 – Claies

+2

它類似於插件,或者考慮模塊化web應用程序,如果園cms。實際上這個程序集的視圖是在用戶給出的運行時進行的! :) –

+1

我不認爲這是可能的,因爲當在dnx環境中使用roslyn時,動態編譯器會使用project.json作爲構建過程的一部分來解析依賴關係。您的動態加載的程序集將不會在project.json中列出,因此編譯器將會失敗。我想在理論上可以動態地調整project.json,然後在啓動之後和視圖加載之前反映新的依賴關係,但老實說,我不知道它是否會起作用,最好是黑客行爲。即使它有效,它也可能在未來破裂。 –

回答

9

1)我不建議讓你的視圖直接使用外部引用或動態加載的外部引用。通過讓您的視圖與控制器進行交互來摘要。讓你的控制器向你的視圖提供一個數據對象,這個數據對象是你的應用程序在構建時已知的(換句話說,在構建時你的web應用程序已知的對象)。這是爲了從您的角度完全隔離(抽象)插件特定的業務。然後讓你的控制器與「插件」進行交互。

2)我不知道你的「定製工廠」是如何工作的,但是現在我們不再真的建立任何「定製工廠」了。相反,我們利用依賴注入容器,如Microsoft Unity(或Ninject,或Castle Windsor等)。創建「自定義工廠」是非常老式的,你基本上已經通過依賴注入來重塑已經解決的問題。

3)至於動態加載外部組件,我不知道,如果你有正確的,但這裏有一個鏈接:

Dynamically load a type from an external assembly

4)通常情況下,一個插件設計暴露已知接口在構建時刻到您的主要Web應用程序。插件設計隱藏的是可以從一個插件更改爲另一個插件的實現。重要的是,每個插件都實現相同的公共接口,即主要Web應用程序所期望的接口。通常,您將在一個單獨的「Common」項目中使用這些接口,這兩個接口都由您的主Web應用程序和實現這些接口的插件引用。因此,從您的主Web應用程序中,您將知道插件的公共接口是什麼,您可以動態加載外部程序集並使用C#反射來查找實現這些接口的類並將它們加載到依賴注入容器中。同樣,任何想要爲您的Web應用程序開發插件的人都必須實現「Common」項目中定義的接口。

注意:「Common」只是我給該項目的隨機名稱。你可以將它命名爲「PluginInterface」或任何你想要的。

之後,讓控制器從依賴注入容器中抓取它所需的任何東西都是微不足道的。

注意:您的插件接口可能會有輸入和輸出實體。這些實體在您的主要Web應用程序和您的插件之間共享。在這種情況下,因爲這些實體是你的接口的一部分,所以他們需要在「Common」項目中。您可能會想要讓您的控制器直接將這些實體返回到您的視圖,但是您的視圖和插件之間不會有完美的抽象。沒有完美的抽象是另一個討論。

希望它有幫助!

+1

你的3在這種情況下是沒有意義的,因爲這個問題是基於你需要影響asp.net動態構建過程的假設。 –

+2

OP的問題是關於「插件設計模式」,我提供了有關正確的方式來做到這一點。它與「ASP.NET動態構建過程」無關。我堅持我的回答。 OP希望他可以使用'BuildManager'來實現他的插件設計模式,但是他發現它與此無關。 – TchiYuan

+2

@Tchi首先,非常感謝你的回答。有很好的東西,但實際上我認爲一個動作的視圖應該能夠訪問該動作所具有的任何命名空間,這似乎是一個正常的期望。 Hovever我有一個明顯的DDD來提供通訊接口,但這不是一個很好的理由在視圖內發出任何引用到它的插件命名空間或服務,如ViewModels,DataProviders,枚舉,... :) –

6

作爲一個系統管理員,我會建議一個維護期,特別是如果你替換的文件混淆了其他的東西。即使您的維護時間只有半小時,這也是一個好習慣。

至於DLL並重新編譯...通常IIS工作進程(運行應用程序池的服務)將根據IIS配置和內存使用情況以正常間隔重新啓動。發生這種情況時,如果有任何需要JIT的應用程序將重新編譯。它還會終止所有打開的用戶會話,因爲它會在物理上停止並重新啓動。工作進程還會監視根目錄(就像您提到的那樣)以進行任何文件更改。如果發現有任何重新編譯被強制。僅僅因爲依賴被改變並不會強制重新編譯。如果您預編譯您的DLL,唯一需要編譯的是您的實際ASPX文件中的任何代碼,並使用每次編譯的JIT。從你所描述的IIS不需要重新編譯或重新啓動,聽起來就像換出文件時IIS掛起的另一個問題。可能需要讓系統管理員參與查看IIS日誌。

祝你好運!

http://msdn.microsoft.com/en-us/library/ms366723.aspx

http://msdn.microsoft.com/en-us/library/bb398860.aspx

+0

其實我手動重新啓動'IIS',但它不完全是我想要的。我希望有一天能得到解決方案或有人幫助。謝謝@Farhad –

2

這裏有一張紙條,上面可以幫助:如果你不是從/bin目錄加載程序集,你需要確保的路徑組件是可發現:

AppDomain.CurrentDomain.AppendPrivatePath(path_to_your-dyna_assembly); 
+2

謝謝你的關注Javad,但不幸的是它並沒有幫助我,但問題不在於此。即使它們從已標記爲「'的路徑加載,它也是可發現的。此外我已經實現了一個適合我的程序集解析器。但是當編譯任何頁面時,編譯器('BuildManager')的上下文不訪問或引用程序集。 –

相關問題