POCO Controller是 ASP.NET Core 中的一个特性,虽然在2015年刚发布的时候就有这个特性了,可是大多数开发者都只是按原有的方式去写,而没有用到这个特性。其实,如果利用这个特性进行稍微封装后,用在SOA架构中Service层的场景中是极其便利的。这篇文章主要就是说我最近在学习使用开源AOP库AspectCore写WebApi动态代理客户端的时候,实现为普通类无添加WebApi服务的过程。
POCO控制器简介
POCO控制器就是ASP.NET Core项目中所有带有Controller
后缀的类、或者标记了[Controller]
特性的类,虽然没有像模版项目中那样继承自Controller类 ,也会被识别为控制器,拥有跟普通控制器一样的功能,像下面这段代码中,两个类都会被识别成控制器:
public class PocoController
{
public IActionResult Index ( )
{
return new ContentResult ( ) {
Content = “ Hello from POCO controller ! ” } ;
}
}
[ Controller ]
public class Poco
{
public IActionResult Index ( )
{
return new ContentResult ( ) {
Content = “ Hello from POCO controller ! ” } ;
}
}
POCO控制器原理
其实,在ASP.NET Core中,已经不像旧版本的 ASP.NET WebApi 那样,通过ControllerFactory来创建Controller,多亏于ASP.NET Core一脉相承的IoC框架 Microsoft.Extensions.DependencyInjection
,ASP.NET Core中的内部实现变得更优雅。其中POCO控制器的核心原理就在IApplicationFeatureProvider<ControllerFeature>
这个接口的实现ControllerFeatureProvider
。
通过aspnet/Mvc项目的Github源码仓库中查询得知,Mvc里把Controller、ViewComponent、TagHelper、Views等组件定义为特性(Feature),如ControllerFeature
,特性里就存放了应用中被识别为相组件的类型的集合,如如ControllerFeature
中就存放了所有Controller
类型。IApplicationFeatureProvider<ControllerFeature>
这个接口是用来给MVC框架提供控制器类型识别的接口,当把这个接口的实现注册到服务配置中,就能为其中识别的类型提供控制器功能。
ControllerFeatureProvider是这个接口的默认实现,其中有一个方法IsController(TypeInfo typeInfo)
的功能就是判断某类型是否为控制器的。而接口方法PopulateFeature(IEnumerable<ApplicationPart> parts,ControllerFeature feature)
则为把传入的 “Mvc应用部分(ApplicationPart
,大概是指Mvc的作用程序集)”中的类型都一一判断,如果是控制器,那么就加入控制器特性对象中。
实现自定义判断规则
通过上面的剖析,我们就知道要实现自定义的控制器判断规则,只需要重写ControllerFeature
类或者重新实现IApplicationFeatureProvider<ControllerFeature>
接口,但是由于PopulateFeature
不是虚方法或抽象方法,所以不能被重写,那么只能重新写一个类来实现IApplicationFeatureProvider<ControllerFeature>
接口了。为了兼容原来规则,我把原来的规则照搬过来,复制了IsController
的方法(开源的好处),并且在PopulateFeature
中加入了自己的规则。先贴代码,避免篇幅过长,IsController
方法的实现就直接链接到源码了: