MSDN裡有描述,VirtualPathProvider只允許在兩個地方註冊:
1. App_Code目錄中任意類的AppInitialize靜態方法。
2. Global.asax中的Application_Start方法中。
而我想知道是,有沒有什麼辦法,可以將VirtualPathProvider註冊的代碼放入外部的dll中,在不需要在App_Code和Global.asax中添加任何代碼的情況下,將VirtualPathProvider通過外部dll自動註冊。或者,只通過web.config配置也行。
(VirtualPathProvider的作用參考:http://www.cnblogs.com/coderzh/archive/2010/01/26/Sharing-Master-Pages-By-DLL.html )
App_Code AppInitialize
在App_Code目錄裡,任意類,實現一個AppInitialize靜態方法,原型:
public static void AppInitialize()
這個方法,將會在Web應用程式初始時自動被調用。因此,考慮在外部dll中定義的AppInitialize方法是否會被執行?
遺憾的是,AppInitialize方法必須在App_Code目錄不可。App_Code目錄是一個非常特殊的目錄,特殊到很多規則你都不知道,ASP.NET對這個目錄的檔案會做一些特殊的處理。就比如AppInitialize靜態方法的執行規則:
1. AppInitialize靜態方法必須是在App_Code目錄下。
2. AppInitialize靜態方法在App_Code目錄下不允許被定義兩次。
如果AppInitialize在App_Code的兩個類中都有定義,比如:
public class SomeClassOne
{
public static void AppInitialize()
{
HostingEnvironment.Cache["InitializationTimeOne"] = DateTime.Now;
}
}
public class SomeClassTwo
{
public static void AppInitialize()
{
HostingEnvironment.Cache["InitializationTimeTwo"] = DateTime.Now;
}
}
編譯時間,將會出現編譯錯誤:
The AppInitialize method is defined both in 'App_Code.SomeClassOne' and in 'App_Code.SomeClassTwo'.
AppInitialize方法在編譯時間就被特殊處理了。推斷,AppInitialize方法想在外面的dll中執行幾乎是不可能的。
Application_Start
Global.asax繼承自HttpApplication,有很多事件(event)可以通過自訂的HttpModule掛上去,比如:AuthenticateRequest,EndRequest。因此,如果HttpApplication有一個類似ApplicationStart的Event,那麼我就可以在外部dll中實現一個自訂的HttpModule,然後再Init函數中,將VirtualPathProvider註冊的代碼掛到ApplicationStart事件中。這樣,要做的僅僅是在Web.config中將自訂的HttpModule加進去。可惜,Application_Start並不提供掛載事件。
Application_Start調用的一些細節參考:http://www.dotnet247.com/247reference/msgs/12/62243.aspx
Web.config
沒有任何跡象表明,允許在Web.config中配置VirtualPathProvider的註冊。
總結:
嘗試的各種方法都失敗了,沒辦法做到不需要在App_Code和Global.asax中添加任何代碼的情況下,通過外部dll將VirtualPathProvider自動註冊。還是老老實實在每個需要用到VirtualPathProvider的工程,在Global.asax的Application_Start方法中添加如下方法:
protected void Application_Start(object sender, EventArgs e)
{
CustomVirtualPathProvider vpp = new CustomVirtualPathProvider();
HostingEnvironment.RegisterVirtualPathProvider(vpp);
}
誰有別的辦法嗎?