ControllerDescriptor與ActionDescriptor的創建
不論是用於描述Controller的ControllerDescriptor,還是用於描述Action方 法的ActionDescriptor,都具有同步和異步兩個版本,那麼這些不同類型的 ControllerDescriptor的ActionDescriptor是在什麼情況下創建的呢?
一、ControllerActionInvoker與AsyncControllerActionInvoker
ControllerDescriptor的創建設計到一個重要的名為ActionInvoker的組件, 顧名思義,ActionInvoker專門用於Action方法的執行。我們會在本書第7章 “Action方法的執行”中對ActionInvoker進行深入介紹,在這裡我們只需要對其 作一個簡單的了解。
ActionInvoker實現了具有如下定義的IActionInvoker接口,唯一的方法實現 了對指定Action方法的執行,而作為Controller的默認基類的Controller具有一 個ActionInvoker屬性,該屬性表示的ActionInvoker被真正用於定義在該 Controller類型中的所有Action方法的執行。
1: public interface IActionInvoker
2: {
3: bool InvokeAction(ControllerContext controllerContext, string actionName);
4: }
5:
6: public abstract class Controller
7: {
8: //其它成員
9: public IActionInvoker ActionInvoker { get; set; }
10: }
而具有如下定義的System.Web.Mvc.Async.IAsyncActionInvoker接口是 ActionInvoker的異步版本。IAsyncActionInvoker繼承了IActionInvoker接口, 並在此基礎上定義了兩個BeginInvokeAction/EndInvokeAction方法用於Action方 法的異步執行。
1: public interface IAsyncActionInvoker : IActionInvoker
2: {
3: IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state);
4: bool EndInvokeAction(IAsyncResult asyncResult);
5: }
ASP.NET MVC真正用於Action方法同步和異步執行的ActionInvoker分別是 ControllerActionInvoker和AsyncControllerActionInvoker。如下面的代碼片斷 所示,ControllerActionInvoker定義了一個受保護的方法 GetControllerDescriptor用於根據指定的Controller上下文獲取相應的 ControllerDescriptor,它的子類AsyncControllerActionInvoker對這個方法進 行了重寫。
1: public class ControllerActionInvoker : IActionInvoker
2: {
3: //其它成員
4: protected virtual ControllerDescriptor GetControllerDescriptor( ControllerContext controllerContext);
5: }
6:
7: public class AsyncControllerActionInvoker : ControllerActionInvoker, IAsyncActionInvoker, IActionInvoker
8: {
9: //其它成員
10: protected override ControllerDescriptor GetControllerDescriptor( ControllerContext controllerContext);
11: }
我們所有要了解的是在默認情況下(沒有對Controller類型的ActionInvoker 屬性進行顯式設置)采用的ActionInvoker類型是哪個。ASP.NET MVC對Conroller 采用的ActionInvoker類型的選擇機制是這樣的:
通過當前的DependencyResolver以IAsyncActionInvoker接口去獲取注冊的 ActionInvoker,如果返回對象不為Null,則將其作為默認的ActionInvoker。
通過當前的DependencyResolver以IActionInvoker接口去獲取注冊的 ActionInvoker,如果返回對象不為Null,則將其作為默認的ActionInvoker。