AOP(Aspect oriented programming)面向切面编程,主要意思是把相同、相似的并且零散的逻辑抽离出来,统一处理,这样不仅维护起来方便,也使得代码更加关注自己本身,清晰明了。
比如我们常见的权限检查,验证登陆,异常处理等都是散乱在系统各个地方,比如管理员在登陆状态才可以添加一个学生信息:
public ActionResult AddStudent(Student student) { if (currentUser != null) { StudentDAL.Add(student); } else { //do something else } }
本来一句StudentDAL.Add(student)就可以实现的功能,现在却要加上if else,还要处理异常,代码显得很难看,如果采用如下的方式:
[HttpPost] [Authorize] public ActionResult AddStudent(Student student) { StudentDAL.Add(student); return View(); }
这种用AuthroizeAttribute特性来处理问题的方式,就是AOP的思想,不仅使代码更加清晰,而且还可以复用这个Attribute。
Attribute只是一种实现方式,Attribute也是在调用具体的action前,通过反射得到Attribute,然后执行代码。像验证登陆可以放在基类Controller中去做判断,而一些细化的权限控制我们可以自定义Attribute来实现。
下面是一个异常处理的例子,如果有一个统一的处理异常的逻辑,那么逻辑代码里就可以不用try catch,而是直接throw exception,会让代码更简洁。(并不是说有了统一处理就再不用try catch了,有些异常还是要去捕获,看具体业务需求,另外捕获不到异常的比如线程里的要注意catch)。
public ActionResult AddStudent(Student student) { if (string.IsNullOrEmpty(student.Name)) { throw new ArgumentException("name"); } return View(); } protected override void OnException(ExceptionContext filterContext) { string filePath = Server.MapPath("~/exception.txt"); using (StreamWriter writer = System.IO.File.AppendText(filePath)) { writer.WriteLine(filterContext.Exception.Message); } base.OnException(filterContext); Response.Redirect("~/Error/NotFound"); }
只要在Controller中重写OnException方法就可以处理该控制器中所有的异常,实现记录异常日志(利用Log4Net),跳转到自定义错误页面等。
当然也可以自定义针对Action的异常处理特性。
public class ExceptionLogFilterAttribute : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { string filePath =HttpContext.Current.Server.MapPath("~/exception.txt"); using (StreamWriter writer = System.IO.File.AppendText(filePath)) { writer.WriteLine(filterContext.Exception.Message); } HttpContext.Current.Response.Redirect("~/Error/NotFound"); } }