
通过代码调试发现,应用启动时遍历了系统中的所有控制器去执行Apply操作,那么通过 IApplicationModelConvention 一样也能实现这个功能,因为它里面包含了控制器集合:
public class ApiControllerAuthorizeConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
foreach (var controller in application.Controllers)
{
if (controller.Filters.Any(x => x is ApiControllerAttribute) && !controller.Filters.Any(x => x is AccessControlFilter))
{
controller.Filters.Add(new AccessControlFilter());
}
}
}
}
再改进一下
实际开发中我的AccessControlFilter需要通过构造函数注入业务接口,类似于这样:
public class AccessControlFilter : IActionFilter
{
private IUserService _userService;
public AccessControlFilter(IUserService service)
{
_userService = service;
}
public void OnActionExecuting(ActionExecutingContext context)
{
//模拟一下业务操作
//var user=_userService.GetById(996);
//.......
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
如何优雅的在Convention中使用DI自动注入呢?Asp.Net Core MVC框架提供的 ServiceFilter 可以解决这个问题, ServiceFilter 本身是一个过滤器,它的不同之处在于能够通过构造函数接收一个Type类型的参数,我们可以在这里把真正要用的过滤器传进去,于是上面的过滤器注册过程演变为:
controller.Filters.Add(new ServiceFilterAttribute(typeof(AccessControlFilter)));
当然了,要从DI中获取这个filter实例,必须要把它注入到DI容器中:
services.AddScoped<AccessControlFilter>();
至此,大功告成,继续愉快的CRUD。
突然想起来我上篇文章提到的扩展DI属性注入功能估计也能通过这个玩意实现,eeeeeee...有空了试一下。
总结
总体来说,我通过曲线救国的方式实现了全局过滤器隔离,虽然去遍历目标控制器再手动添加Filter的方式没有那种一行代码就能实现的方式优雅,但我大体来说还算满意,是目前能想到的最好办法。我估摸着, options.Filters.Add(xxx) 也是在框架某个时候一个个把xxx丢给各自主人的,瞎猜的,说错不负责~hhhh:see_no_evil::see_no_evil::see_no_evil:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易采站长站。








