关于ASP.NET MVC对请求的处理方式(同步或者异步)涉及到的五个组件,在《上篇》中我们谈了三个(MvcHandler、Controller和 ActionInvoker),现在我们来谈余下的两个,即ControllerDescriptor和ActionDescriptor,这五个组件的 执行并非孤立的,而是具有议定的关系。相信读者认真阅读了这两篇文章后,会对整个请求的处理方式有一个深刻的理解。
四、ControllerDescriptor的同步与异步
如 果采用ControllerActionInvoker,Action总是以同步的方式来直接,但是当 AsyncControllerActionInvoker作为Controller的ActionInvoker时,并不意味着总是以异步的方式来执行 所有的Action。至于这两种类型的ActionInvoker具体采用对Action的怎样的执行方式,又涉及到两个描述对象,即用于描述 Controller和Action的ControllerDescriptor和ActionDescriptor。
通过前面 “Model的绑定”中对这两个对象进行过相应的介绍,我们知道在ASP.NET MVC应用编程接口中具有两个具体的ControllerDescriptor,即ReflectedControllerDescriptor和 ReflectedAsyncControllerDescriptor,它们分别代表同步和异步版本的ControllerDescriptor。
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
ReflectedControllerDescriptor 和ReflectedAsyncControllerDescriptor并非对分别实现了IController和IAyncController接口 的Controller的描述,而是对直接继承自抽象类Controller和AsyncController的Controller的描述。它们之间的 区别在于创建者的不同,在默认情况下ReflectedControllerDescriptor和 ReflectedAsyncControllerDescriptor分别是通过ControllerActionInvoker和 AsyncControllerActionInvoker来创建的。ActionInvoker和ControllerDescriptor之间的关系 可以通过如下图所示的UML来表示。
ActionInvoker 与ControllerDescriptor之间的关系可以通过一个简单的实例来验证。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中,我们自定义了如下两个分别继承自ControllerActionInvoker和 AsyncControllerActionInvoker的ActionInvoker类型。在这两个自定义ActionInvoker中,定义了公有 的GetControllerDescriptor方法覆盖了基类的同名方法(受保护的虚方法),并直接直接调用基类的同名方法根据提供的 Controller上下文的到相应的ControllerDescriptor对象。
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
然 后我们定义了两个Controller类型,它们均是抽象类型Controller的直接继承者。如下面的代码片断所示,这两Controller类 (FooController和BarController)都重写了虚方法CreateActionInvoker,而返回的 ActionInvoker类型分别是上面我们定义的FooActionInvoker和BarActionInvoker。在默认的Action方法 Index中,我们利用当前的ActionInvoker得到用于描述本Controller的ControllerDescriptor对象,并将其类 型呈现出来。
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
现 在我们运行我们的程序,并在浏览器中输入相应的地址对定义在FooController和BarController的默认Action方法Index发 起访问,相应的ControllerDescriptor类型名称会以下图所示的形式呈现出来,它们的类型分别是 ReflectedControllerDescriptor和ReflectedAsyncControllerDescriptor。
五、ActionDescriptor的执行
Controller 包含一组用于描述Action方法的ActionDescriptor对象。由于Action方法可以采用同步和异步执行方法,异步Action对应的 ActionDescriptor直接或者间接继承自抽象类AsyncActionDescriptor,后者是抽象类ActionDescriptor 的子类。如下面的代码片断所示,同步和异步Action的执行分别通过调用Execute和BeginExecute/EndExecute方法来完成。 值得一提的是,AsyncActionDescriptor重写了Execute方法并直接在此方法中抛出一个 InvalidOperationException异常,也就是说AsyncActionDescriptor对象只能采用 异步执行方式。
发表回复