按照AOP思想自定义特性,比如登录校检,处理登录方法Login不需要校检,其他的Action都要进行登录校检。怎么将做一个能处理上述逻辑的登录校检呢?我们自定义两个特性,一个是忽略登录校验特性IgnoreLoginAttribute和校验登录特性CheckLoginAttribute。
按照AOP思想,我们肯定是要把校检登录特性进行提取做一个全局的特性,CheckLoginAttribute伪代码和IgnoreLoginAttribute伪代码如下:
/// <summary> /// 校验登录 /// </summary> public class CheckLoginAttribute : FilterAttribute, IActionFilter {
public ILogger _logger { get; set; } /// <summary> /// Action执行之前执行 /// </summary> /// <param name="filterContext">过滤器上下文</param> public void OnActionExecuting(ActionExecutingContext filterContext) {
try {
//判断是否需要登录 bool needLogin = !filterContext.ContainsAttribute<IgnoreLoginAttribute>(); //转到登录 if (needLogin) RedirectToLogin();
else return;
}
catch (Exception ex) { _logger.Error(ex); RedirectToLogin(); }
}
/// <summary> /// Action执行完毕之后执行 /// </summary> /// <param name="filterContext"></param> public void OnActionExecuted(ActionExecutedContext filterContext) { } }
/// <summary> /// 忽略登录校验 /// </summary> public class IgnoreLoginAttribute : Attribute { }
我们会对特性CheckLoginAttribute在适当的地方做一个全局的配置。本文重点是ActionExecutingContext的扩展类,就不对全局配置做详细概述。
对于不需要登录校检的Action上加入特性IgnoreLoginAttribute,全局特性CheckLoginAttribute中有一个逻辑判断:即ActionExecuting上下文做了扩展方法,用来判断请求的Action是否加入了IgnoreLoginAttribute特性。
bool needLogin = !filterContext.ContainsAttribute<IgnoreLoginAttribute>();
接下来就是介绍本文的重点ActionExecutingContext的扩展类ContainsAttribute
public static partial class Extention { /// <summary> /// 获取所有AOP特性
/// 通过上下文获取所有控制器和方法的特性 /// </summary> /// <param name="filterContext">AOP对象</param> /// <param name="inherit">是否继承父类</param> /// <returns></returns> public static List<Attribute> GetAllCustomAttributes(this ActionExecutingContext filterContext, bool inherit=true) { var actionAttrs = filterContext.ActionDescriptor.GetCustomAttributes(inherit).Select(x=>x as Attribute).ToList(); var controllerAttrs = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(inherit).Select(x=>x as Attribute).ToList(); return actionAttrs.Concat(controllerAttrs).ToList(); } /// <summary> /// 是否包含某特性 /// </summary> /// <typeparam name="T">特性类型</typeparam> /// <param name="filterContext">AOP对象</param> /// <returns></returns> public static bool ContainsAttribute<T>(this ActionExecutingContext filterContext) where T : Attribute { return filterContext.GetAllCustomAttributes().Any(x => x.GetType() == typeof(T)); } }