ASP.NET MVC涉及到的5个同步与异步,你是否傻傻分

关于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:publicclass ReflectedControllerDescriptor : ControllerDescriptor

 

双击代码全选

1

2: {

 

双击代码全选

1

3://省略成员

 

双击代码全选

1

4: }

 

双击代码全选

1

 

 

双击代码全选

1

6:publicclass ReflectedAsyncControllerDescriptor : ControllerDescriptor

 

双击代码全选

1

7: {

 

双击代码全选

1

8://省略成员

 

双击代码全选

1

9: }

 

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:publicclass FooActionInvoker : ControllerActionInvoker

 

双击代码全选

1

2: {

 

双击代码全选

1

3:publicnew ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)

 

双击代码全选

1

4:     {

 

双击代码全选

1

5:returnbase.GetControllerDescriptor(controllerContext);

 

双击代码全选

1

6:     }

 

双击代码全选

1

7: }

 

双击代码全选

1

 

 

双击代码全选

1

9:publicclass BarActionInvoker : AsyncControllerActionInvoker

 

双击代码全选

1

10: {

 

双击代码全选

1

11:publicnew ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext)

 

双击代码全选

1

12:     {

 

双击代码全选

1

13:returnbase.GetControllerDescriptor(controllerContext);

 

双击代码全选

1

14:     }

 

双击代码全选

1

15: }

 

然 后我们定义了两个Controller类型,它们均是抽象类型Controller的直接继承者。如下面的代码片断所示,这两Controller类 (FooController和BarController)都重写了虚方法CreateActionInvoker,而返回的 ActionInvoker类型分别是上面我们定义的FooActionInvoker和BarActionInvoker。在默认的Action方法 Index中,我们利用当前的ActionInvoker得到用于描述本Controller的ControllerDescriptor对象,并将其类 型呈现出来。

双击代码全选

1

1:publicclass FooController : Controller

 

双击代码全选

1

2: {

 

双击代码全选

1

3:protectedoverride IActionInvoker CreateActionInvoker()

 

双击代码全选

1

4:     {

 

双击代码全选

1

5:returnnew FooActionInvoker();

 

双击代码全选

1

6:     }

 

双击代码全选

1

 

 

双击代码全选

1

8:publicvoid Index()

 

双击代码全选

1

9:     {

 

双击代码全选

1

10:         ControllerDescriptor controllerDescriptor = ((FooActionInvoker)this.ActionInvoker).GetControllerDescriptor(ControllerContext);

 

双击代码全选

1

11:         Response.Write(controllerDescriptor.GetType().FullName);

 

双击代码全选

1

12:     }

 

双击代码全选

1

13: }

 

双击代码全选

1

14:

 

双击代码全选

1

15:publicclass BarController : Controller

 

双击代码全选

1

16: {

 

双击代码全选

1

17:protectedoverride IActionInvoker CreateActionInvoker()

 

双击代码全选

1

18:     {

 

双击代码全选

1

19:returnnew BarActionInvoker();

 

双击代码全选

1

20:     }

 

双击代码全选

1

21:

 

双击代码全选

1

22:publicvoid Index()

 

双击代码全选

1

23:     {

 

双击代码全选

1

24:         ControllerDescriptor controllerDescriptor = ((BarActionInvoker)this.ActionInvoker).GetControllerDescriptor(ControllerContext);

 

双击代码全选

1

25:         Response.Write(controllerDescriptor.GetType().FullName);

 

双击代码全选

1

26:     }

 

双击代码全选

1

27: }

 

现 在我们运行我们的程序,并在浏览器中输入相应的地址对定义在FooController和BarController的默认Action方法Index发 起访问,相应的ControllerDescriptor类型名称会以下图所示的形式呈现出来,它们的类型分别是 ReflectedControllerDescriptor和ReflectedAsyncControllerDescriptor。

五、ActionDescriptor的执行

Controller 包含一组用于描述Action方法的ActionDescriptor对象。由于Action方法可以采用同步和异步执行方法,异步Action对应的 ActionDescriptor直接或者间接继承自抽象类AsyncActionDescriptor,后者是抽象类ActionDescriptor 的子类。如下面的代码片断所示,同步和异步Action的执行分别通过调用Execute和BeginExecute/EndExecute方法来完成。 值得一提的是,AsyncActionDescriptor重写了Execute方法并直接在此方法中抛出一个 InvalidOperationException异常,也就是说AsyncActionDescriptor对象只能采用 异步执行方式。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Grow your business fast with

Suku