接口:IExtensibleObject、IExtension和IExtensionCollection,這是可擴展對象模式中最重要的三個接口,也只有這三個接口。
IExtensibleObject天然是定義了可擴展對象,即咱們要對誰進行擴展,它的定義很是簡單,僅僅是提供了一個只讀的屬性Extensions,用來提供全部擴展對象的集合,以下代碼所示:
public interface IExtensibleObject<T> where T : IExtensibleObject<T>
{
IExtensionCollection<T> Extensions { get; }
}
IExtension定義了擴展對象的契約,使對象能夠經過聚合擴展另外一個對象(此處的另外一個對象,就是指上面所講的擴展宿主IExtensibleObject),在IExtension中定義了兩個很是重要的方法Attach和Detach方法,分別用來提供聚合或解聚的通知。
public interface IExtension<T> where T : IExtensibleObject<T>
{
void Attach(T owner);
void Detach(T owner);
}
當一個擴展對象IExtension附加到可擴展對象的擴展集合中時,它的Attach方法將會被調用;反之若是從集合中移除一個擴展對象時,它的Detach方法會被調用。這一點咱們能夠經過Reflector來獲得驗證,以下代碼所示:
protected override void InsertItem(int index, IExtension<T> item)
{
lock (base.SyncRoot)
{
item.Attach(this.owner);
base.InsertItem(index, item);
}
}
protected override void RemoveItem(int index)
{
lock (base.SyncRoot)
{
base.Items[index].Detach(this.owner);
base.RemoveItem(index);
}
}
最後一個接口是IExtensionCollection,它是IExtension對象的集合。
對HttpApplication進行擴展
下面咱們就看一下如何使用可擴展對象模式對HttpApplication進行擴展,首先定義可擴展對象,讓ExtensibleHttpApplication派生於HttpApplication,並實現了IExtensibleObject接口,泛型的參數類型就是它自身,以下代碼所示:
public class ExtensibleHttpApplication : HttpApplication,
IExtensibleObject<ExtensibleHttpApplication>
{
private IExtensionCollection<ExtensibleHttpApplication> _extensions;
public ExtensibleHttpApplication()
{
this._extensions = new ExtensionCollection<ExtensibleHttpApplication>(this);
}
public IExtensionCollection<ExtensibleHttpApplication> Extensions
{
get
{
return this._extensions;
}
}
}
有了可擴展的HttpApplication以後,須要在HttpApplication中實現任何功能,均可以做爲一個擴展附加到ExtensibleHttpApplication上去,如實現ASP.NET MVC路由,能夠定義一個以下代碼所示的擴展對象:
public class MvcHttpApplication : IExtension<ExtensibleHttpApplication>
{
public void Attach(ExtensibleHttpApplication owner)
{
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
public void Detach(ExtensibleHttpApplication owner)
{
//nothing
}
}
一樣若是要在HttpApplication中啓動Workflow,能夠再針對Workflow定義一個擴展對象,以下示例代碼所示:
public class WorkflowHttpApplication : IExtension<ExtensibleHttpApplication>
{
private WorkflowRuntime workflowRuntime;
public void Attach(ExtensibleHttpApplication owner)
{
workflowRuntime = new WorkflowRuntime("workflowServicesConfig");
ExternalDataExchangeService externalDataExchangeService = new ExternalDataExchangeService();
workflowRuntime.AddService(externalDataExchangeService);
workflowRuntime.StartRuntime();
}
public void Detach(ExtensibleHttpApplication owner)
{
workflowRuntime.StopRuntime();
}
}
咱們已經定義好了相應的擴展對象,只須要在相應的HttpApplication把擴展對象附加到ExtensibleHttpApplication上便可,修改Global.asax中的代碼以下所示:
public class MvcApplication : ExtensibleHttpApplication
{
protected void Application_Start()
{
this.Extensions.Add(new MvcHttpApplication());
this.Extensions.Add(new WorkflowHttpApplication());
}
}
如今代碼是否是看起來優雅多了?如今若是要在Application_Start中,添加另一些執行代碼,只須要編寫相應的擴展對象,並將其添加到Extension集合中便可。也許有朋友會問,這樣每添加一些新的代碼,仍是要修改Application_Start中的代碼啊?別忘了,能夠經過配置能夠解決這個問題,WCF中的擴展不也是能夠採用配置方式實現,不是嗎?一樣,若是咱們須要在Application_End事件中釋放某些對象,能夠直接從擴展集合中移除它,此時將會調用它的Detach方法。
總結
本文介紹瞭如何使用WCF中提供的可擴展對象模式擴展HttpApplication,事實上可擴展對象模式的做用遠不在此,它能夠擴展.NET類庫中任何咱們想對其進行擴展的對象,或者是一個自定義的類型,均可以使用可擴展對象模式對其進行擴展。
注1:因爲TerryLee最近一段時間忙於別的事務,無暇顧及Blog,因此有大量的評論和E-mail都沒能回覆,請你們見諒。