天天看點

一起談.NET技術,技巧:使用可擴充對象模式擴充HttpApplication

  HttpApplication對象對于做ASP.NET開發的朋友,我想沒有人不熟悉它。在ASP.NET開發中,經常避免不了要在HttpApplication中執行一些操作,如使用了ASP.NET MVC架構,就會在Application_Start 事件中避免不了這樣的路由規則配置代碼:

  如果僅僅是這一條,看起來倒不覺的有什麼問題,但如果同時在應用程式中使用了工作流,又避免不了在Application_Start出現啟動工作流運作時的代碼:

  試想一下,現在我們僅僅是有了ASP.NET MVC路由規則的配置、WF運作時的啟動,如果在應用程式中使用某種DI架構,如微軟的Unity,是不是又避免不了要出現這樣的容器初始化代碼呢?

  再看看Application_Start事件中的代碼,有ASP.NET MVC的工作,有WF的工作,也有Unity的工作,不知道将來還會有什麼?這些原本互相之間沒有任何聯系的代碼,現在卻同時堆在了一起,當每一部分(或者說每一個架構)變化的時候,都會涉及到Application_Start中代碼的修改,顯然違反了OCP原則。那麼有沒有一種機制,讓這些互不相幹的子產品之間互相獨立,各自發生變化時不影響對HttpApplication?此時我們就需要對HttpApplication進行擴充,提供一個擴充點,讓其他子產品的程式附加到HttpApplication上面。

  我們知道WCF提供了非常完美的擴充機制,幾乎在服務執行過程中的每一個環節上都提供有擴充點,如ServiceHostBase、OperationContext、InstanceContext、IContextChannel,這些對象都屬于可擴充對象,它們都通過Extensions屬性擷取用于所有擴充的集合。我們能不能使用這種方式對HttpApplication也進行擴充呢,答案自然是肯定的。查閱一下MSDN就會知道在System.ServiceModel命名空間下面提供了這樣的一組接口:IExtensibleObject、IExtension和IExtensionCollection,這是可擴充對象模式中最重要的三個接口,也隻有這三個接口。

  IExtensibleObject自然是定義了可擴充對象,即我們要對誰進行擴充,它的定義非常簡單,僅僅是提供了一個隻讀的屬性Extensions,用來提供所有擴充對象的集合,如下代碼所示:

  IExtension定義了擴充對象的契約,使對象可以通過聚合擴充另一個對象(此處的另一個對象,就是指上面所講的擴充宿主IExtensibleObject),在IExtension中定義了兩個非常重要的方法Attach和Detach方法,分别用來提供聚合或解聚的通知。

  當一個擴充對象IExtension附加到可擴充對象的擴充集合中時,它的Attach方法将會被調用;反之如果從集合中移除一個擴充對象時,它的Detach方法會被調用。這一點我們可以通過Reflector來得到驗證,如下代碼所示:

  最後一個接口是IExtensionCollection,它是IExtension對象的集合。

  下面我們就看一下如何使用可擴充對象模式對HttpApplication進行擴充,首先定義可擴充對象,讓ExtensibleHttpApplication派生于HttpApplication,并實作了IExtensibleObject接口,泛型的參數類型就是它自身,如下代碼所示:

  有了可擴充的HttpApplication之後,需要在HttpApplication中實作任何功能,都可以作為一個擴充附加到ExtensibleHttpApplication上去,如實作ASP.NET MVC路由,可以定義一個如下代碼所示的擴充對象:

  我們已經定義好了相應的擴充對象,隻需要在相應的HttpApplication把擴充對象附加到ExtensibleHttpApplication上即可,修改Global.asax中的代碼如下所示:

  現在代碼是不是看起來優雅多了?現在如果要在Application_Start中,添加另外一些執行代碼,隻需要編寫相應的擴充對象,并将其添加到Extension集合中即可。也許有朋友會問,這樣每添加一些新的代碼,還是要修改Application_Start中的代碼啊?别忘了,可以通過配置可以解決這個問題,WCF中的擴充不也是可以采用配置方式實作,不是嗎?同樣,如果我們需要在Application_End事件中釋放某些對象,可以直接從擴充集合中移除它,此時将會調用它的Detach方法。

  本文介紹了如何使用WCF中提供的可擴充對象模式擴充HttpApplication,事實上可擴充對象模式的作用遠不在此,它可以擴充.NET類庫中任何我們想對其進行擴充的對象,或者是一個自定義的類型,都可以使用可擴充對象模式對其進行擴充。

繼續閱讀