AOP(Aspect-oriented programming)
名词解释
Aspect
意思为剖面,Oriented
意思为导向,所以翻译为剖面导向程式设计
,这意思恐怕很难直接从字面上理解,技术人员就直接用程式来说明吧。
一般我们在写程式时,很常需要处理譬如错误纪录
、权限验证
,乃至于额外可能增加使用者查询历程
等等,就以错误纪录来说,一个方法(Function)要用Nlog进行错误纪录,通常会是这样子。
public int TestFunction(int num1, int num2){ int result; try{ result = num1 + num2; } catch (Exception ex){ var logger = LogManager.GetLogger(invocation.GetType().FullName); logger.Error(ex, ex.Message); } return result;}
如果系统不大,就那十几个方法,複製贴上也就解决,但如果是个大系统,几百个方法要写的话,勤劳的人也许可以做几百次複製贴上,但是生性懒惰的我根本不会想这样蛮干,而AOP这个架构的诞生,就是基于要减少类似这样的重工。
架构
画个图来看,一般我们写的方法流程,基本是这个样子的。
举例,每个方法都有自己的两个验证机制以及一个错误处理,若是有200个方法的话就要做597次的重工,而改採用AOP的架构的话,验证机制与错误处理只要各写一次,其他方法只要在方法上或者是Service上加个标籤(Attribute),马上省掉这597次的重工,而此时方法的流程就会呈现如下。
这个图也就是AOP的中心思想,将直向流程的方法,抽离出共用逻辑,再将共通逻辑从侧面横切插入到原本的方法,透过AOP,我们可以达成软体工程的两个概念。
关注点分离(Separation of concerns, SOC):分离商业逻辑与共通逻辑,使程式设计师能将更多心力放在主逻辑上,更好的避免错误的发生。开放封闭原则(Open–closed principle, OCP):OCP是这样解释的,对于扩展是开放的,对于修改是封闭的,当套用AOP概念后,如果要对方法加入更多验证,或是更多杂七杂八的机制,我们都可以透过AOP,完成后挂载在方法之上,这就是对扩展的开放,但相对的我们并不会修改到主逻辑本身,这也应证了对修改是封闭的。如何实作
如果是.Net MVC专案的话,在Controller上可以透过ActionFilter
这个标籤来完成AOP的功能,但无法套用在普通的方法上,目前也没有Nuget套件可以直接拿来用,要实作的话,可以用Autofac.Extras.DynamicProxy
的Intercept
(拦截)标籤,但是要额外加工,并且自订Interceptor
(拦截器)的内容,拦截,顾名思义就是在方法执行的时候,先把方法暂停一下,可以取得他传入的参数以及回传值的类型,而拦截器定义的内容就是你要为方法进行甚么样的处理,例如错误纪录。
使用Autofac的Intercept,在interface或service class上加上这样的标籤,而方法内容只要专注于商业逻辑就好,如下。
using Autofac.Extras.DynamicProxy;//例外处理的AOP标籤[Intercept(typeof(ExceptionLogInterceptor))]public class Service{ public int TestFunction(int num1, int num2) { return num1 + num2; }}
ExceptionLogInterceptor
,就是自订的Interceptor(拦截器),以这个例子来说,这个Interceptor是我用来处理错误纪录的,如此一来,这个Service的方法都可以处理错误纪录。
要使用Autofac.Extras.DynamicProxy
记得也要装Autofac(DI Container)
更详细的实作方法,在接下来的系列文章当中会有更加详细的说明,请原谅我在这边卖个关子,敬请期待。
总结
使用AOP架构好处多多,减少重工又可以让你的程式码更加简单易懂,因为共用的逻辑抽离之后,就只需要专注于商业逻辑的撰写,只是对于C#新手来说,可能门槛比较高,不过整体来说,专案若是套用了AOP架构后,整个大升级,不管几百几千的方法,如果要加上一堆共用基制的话,都不用怕啦,人挡杀人,佛挡杀佛,不好意思有点激动:D
后记
这边文章比较少讲到一些AOP专业术语或者是更详细的原理,是基于我个人对AOP的认识,来与大家分享,请各位鞭小力一点 :P好像一直讲到抽离共用逻辑,专注于商业逻辑
,不过因为真的很重要,多提几次应该也无妨(?)参考资源
AOP 观念与术语
Autofac
Autofac.Extras.DynamicProxy