(给DotNet加星标,提升.Net技能)
转自: Artech cnblogs.com/artech/p/inside
ASP.NET Core框架建立在一些核心的基础框架之上,这些基础框架包括依赖注入、文件系统、配置选项和诊断日志等。这些框架不仅仅是支撑ASP.NET Core框架的基础,我们在进行应用开发的时候同样会频繁地使用到它们。
一、流程控制的反转
软件开发中的一些所谓的设计理念往往没有一个明确的定义,比如之前流行的SOA和现在炒得火热的"微服务(Micro Service)"和"无服务器(Serverless)",我们都没法通过一个明确的"内涵"给它们一个准确的定义,而只能从"外延"上描述这些架构设计应该具有怎样的特性。
public static class MvcLib
{
public static Task ListenAsync(Uri address);
public static Task<Request> ReceiveAsync();
public static Task<Controller> CreateControllerAsync(Request request);
public static Task<View> ExecuteControllerAsync(Controller controller);
public static Task RenderViewAsync(View view);
}
MvcLib提供了如上5个方法帮助我们完成整个HTTP请求流程中的5个核心任务。具体来说,ListenAsync方法启动一个监听器并将其绑定到指定的地址进行HTTP请求的监听,抵达的请求通过ReceiveAsync方法进行接收,接收到的请求通过一个Request对象来表示。
class Program
{
static async Task Main()
{
while (true)
{
var address = new Uri("http://0.0.0.0:8080/mvcapp");
await MvcLib.ListenAsync(address);
while (true)
{
var request = await MvcLib.ReceiveAsync();
var controller = await MvcLib.CreateControllerAsync(request);
var view = await MvcLib.ExecuteControllerAsync(controller);
await MvcLib.RenderViewAsync(view);
}
}
}
}
这个例子体现了如下图所示的流程控制方式(应用的代码完全采用异步的方式来处理请求,为了让流程图显得更加简单,我们在流程图中画成了同步的形式,读者不必纠结这个问题)。我们设计的类库(MvcLib)仅仅通过API的形式提供各种单一功能的实现,作为类库消费者的应用程序(App)则需要自行编排整个工作流程。如果从代码重用的角度来讲,这里被重用的仅限于实现某个环节单一功能的代码,编排整个工作流程的代码并没有得到重用。
但是在真实开发场景下,我们需要的不仅仅是一个能够提供单一API的类库,而是能够直接在上面构建应用的框架。
如果你曾经开发过ASP.NET MVC应用,你会发现ASP.NET MVC就是这么一个框架。
有了前面演示的这个例子作为铺垫,我们应该很容易理解IoC所谓的控制反转本质上说的是什么了。总的来说,IoC是我们设计框架所采用的一种基本思想,所谓的控制反转就是将应用对流程的控制转移到框架中。拿前面这个例子来说,在传统面向类库编程的时代,针对HTTP请求处理的流程牢牢控制在应用程序手中。在引入框架之后,请求处理的控制权转移到了框架手中。
二、好莱坞法则
在好莱坞,演员把简历递交给演艺公司后就只有回家等待。由于演艺公司对整个娱乐项目具有完全控制权,演员只能被动地接受电影公司的邀约。
"不要给我们打电话,我们会给你打电话(Don't call us, we'll call you)"这是著名的好莱坞法则( Hollywood Principle或者 Hollywood Low),IoC完美地体现了这一法则。
在IoC的语境中,框架就像是掌握整个电影制片流程的电影公司,由于它是整个工作流程的实际控制者,所以只有它知道哪个环节需要哪些人员。
IoC几乎是所有框架均具有的一个固有属性,从这个意义上讲,"IoC框架"的说法其实是错误的,世界上并没有什么IoC框架,或者说所有的框架都是IoC框架。
三、流程定制
我们采用IoC实现了流程控制从应用程序向框架的转移,但是被转移的仅仅是一个泛化的流程,任何一个具体的应用都可能需要对该流程的某些环节进行定制。
还是以我们的MVC框架来说,默认实现的请求处理流程可以只考虑针对HTTP 1.1的支持,但是我们在设计框架的时候应该提供相应的扩展点来支持HTTP 2。
作为一个Web框架,用户认证功能是必备的,但是框架自身不能限制于某一种或者几种固定的认证方式,它应该允许我们通过扩展实现任意的认证模式。
我们可以说得更加宽泛点。如下图所示,我们将一个泛化的工作流程(A=>B=>C)定义在框架之中,建立在该框架的两个应用需要对组成这个流程的某些环节进行定制。比如步骤A和C可以被App1重用,但是步骤B却需要被定制(B1)。App2则重用步骤A和B,但是需要按照自己的方式处理步骤C。
IoC将对流程的控制从应用程序转移到框架之中,框架利用一个引擎驱动整个流程的自动化执行。应用程序无需关心工作流程的细节,它只需要启动这个引擎即可。
这个引擎一旦被启动,框架就会完全按照预先编排好的流程进行工作,如果应用程序希望整个流程按照自己希望的方式被执行,需要在启动之前对流程进行定制。
一般来说,框架会以相应的形式提供一系列的扩展点,应用程序通过注册扩展的方式实现对流程某个环节的定制。
在引擎被启动之前,应用程序将所需的扩展注册到框架之中。一旦引擎被正常启动,这些注册的扩展会自动参与到整个流程的执行过程中。
综上所述,IoC一方面通过流程控制从应用程序向框架的反转实现了针对流程自身的重用,另一方面通过内置的扩展机制使这个被重用的流程能够自由地被定制,这两个因素决定了框架自身的价值。
重用让框架不仅仅是为应用程序提供实现单一功能的API,而是提供一整套可执行的解决方案,可定制则使我们可以为不同的应用程序对框架进行定制,这无疑让框架可以使用到更多的应用之中。
推荐阅读
(点击标题可跳转阅读)
看完本文有收获?请转发分享给更多人
关注「DotNet」加星标,提升.Net技能
好文章,我在看❤️