App_Code 是一個 ASP.NET 網站專案的特殊子目錄。如果你的專案不是 Web Site 專案而是 Web Application 專案, 你並不需要、也不應該特別建立一個 App_Code 子目錄來存放你的程式碼 -- 除非是為了某種特殊的目的。
例如, 如果你希望幫網站加入動態產生版本的功能的話, 那麼你可以建立 App_Code 子目錄 (在這裡都使用 Web Application 專案), 並且在這個子目錄下隨便建立一個如下的類別檔:
using System; using System.Web; using System.Web.UI; using System.Web.Configuration; using System.Web.Compilation; using System.CodeDom; using System.Reflection; [assembly: AssemblyVersion("0.9.*")] namespace DbModel { public class Helper { ... } }
然後, 你可以使用以下程式碼取出以上類別檔的動態版本號碼, 當作的網站的版本號碼:
using System; using System.Reflection; using DbManager; using System.Threading; ... Assembly web = Assembly.Load("App_Code"); AssemblyName webName = web.GetName(); lbVersion.Text = string.Format("網站版本: {0}.{1}.{2}", webName.Version.Major, webName.Version.Minor, webName.Version.Build); //lbVersion.Text += webName.Version.ToString();
如此一來, 在 lbVersion 處顯示的網站版本, 就會依照 0.9.* 的格式逐次編號 (例如 0.9.5084.24242), 而且每次網站編譯後, 它的版本號碼都會比上一次大, 所以可以作為每次發行時的版號參考依據。
照理說, 對於 Web Application 專案而言, App_Code 的作用應該即止於此。
然而, 如果你想擴充這個類別的功能, 難道不行嗎?
我剛好就是這樣想的。我就把 App_Code 當作其它子目錄一樣用了; 我在上面那個 Helper 類別中加上了許多功能, 直到遇到問題為止。什麼問題呢? 我突然發現它無法存取參考進來的 dll。
例如, 我在同一個方案中建立了一個另一個 DbModel 專案, 並且已經把參考加入了網站的 reference, 但是偏偏只有在 App_Code 之下的 Helper 類別無法存取那個 reference。甚至, 如果我在程式開頭加上 using DbModel, 那麼即使編譯能過, 在執行時它還是發出一個找不到參考的錯誤! 看起來, 這個 App_Code 在 Web Application 專案裡確實仍然是一個特殊的子目錄!
其實我只需要把程式移到 App_Code 之外就行了。但是我發揮了鍥而不捨的精神, 非把它克服為止, 所以才有這篇文章的出現。
我要做的事情並不複雜, 我只想要取出 DbModel 命名空間之下某個類別的某個欄位的預設值而已。
於是我花了一點時間去研究和 trial and error, 發現我可以把那個外部 dll 載入, 再設法呼叫它的欄位值, 以下就是我的程式碼 (寫在 Helper 類別裡面):
Assembly a = Assembly.Load("DbModel"); Type myType = a.GetType("DbModel.MyData"); FieldInfo field = myType.GetField("MyString"); string myString = (string)field.GetValueDirect(__makeref(myType)); return myString;
在上述程式中, 我使用了 GetField 去取出欄位。如果你想取出的不是欄位的話, 你也可以使用 GetProperty 和 GetMethod 方式取出屬性和方法; 而方法則可以再使用 Invoke 方法去予以呼叫。
不過上述程式中最困難的技巧在於 GetValueDirect 方法。我發現我只能使用 __makeref 這個 undocumented 函式才能產生一個 TypedReference 物件以作為參考。雖然說使用 undocumented 函式並不是值得推薦的方法, 但是我實在已經找不到其它更好的方法了。
以上僅供參考。
沒有留言:
張貼留言