一、AOP观点
老例子,照样先看官方诠释:AOP(Aspect-Oriented Programming,面向切面的编程),它是可以经由过程预编译体式格局和运行期动态代办实如今不修正源代码的情况下给递次动态一致增加功用的一种手艺。它是一种新的要领论,它是对传统OOP编程的一种补充。OOP是关注将需求功用划分为差别的而且相对自力,封装优越的类,并让它们有着属于本身的行动,依托继续和多态等来定义相互的关联;AOP是愿望可以将通用需求功用从不相干的类当中分离出来,可以使得很多类同享一个行动,一旦发作变化,没必要修正很多类,而只需要修正这个行动即可。AOP是运用切面(aspect)将横切关注点模块化,OOP是运用类将状况和行动模块化。在OOP的天下中,递次都是经由过程类和接口构造的,运用它们完成递次的中心营业逻辑是非常适宜。然则关于完成横切关注点(逾越运用递次多个模块的功用需求)则非常费劲,比方日记纪录,权限考证,非常阻拦等。
博主的明白:AOP就是将公用功用提取出来,假如今后公用功用的需求发作变化,只需要修改公用的模块的代码即可,多个挪用的处所则不需要修改。所谓面向切面,就是只关注通用功用,而不关注营业逻辑。完成体式格局平常是经由过程阻拦。比方,我们随意一个Web项目基础都有的权限考证功用,进入每一个页眼前都邑校验当前登录用户是不是有权限检察该界面,我们不能够说在每一个页面的初始化要领内里都去写这段考证的代码,这个时刻我们的AOP就派上用场了,AOP的机制是预先定义一组特征,使它具有阻拦要领的功用,可以让你在实行要领之前和以后做你想做的营业,而我们运用的时刻只需要的对应的要领或许类定义上面加上某一个特征就好了。
二、运用AOP的上风
博主以为它的上风重要表如今:
1、将通用功用从营业逻辑中抽离出来,可以省略大批反复代码,有利于代码的操作和保护。
2、在软件设想时,抽出通用功用(切面),有利于软件设想的模块化,下降软件架构的庞杂度。也就是说通用的功用都是一个零丁的模块,在项目的主营业内里是看不到这些通用功用的设想代码的。
三、AOP的简朴运用
为了申明AOP的事情道理,博主盘算先从一个简朴的例子最先,经由过程静态阻拦的体式格局来相识AOP是怎样事情的。
1、静态阻拦
public class Order { public int Id { set; get; } public string Name { set; get; } public int Count { set; get; } public double Price { set; get; } public string Desc { set; get; } } public interface IOrderProcessor { void Submit(Order order); } public class OrderProcessor : IOrderProcessor { public void Submit(Order order) { Console.WriteLine("提交定单"); } } public class OrderProcessorDecorator : IOrderProcessor { public IOrderProcessor OrderProcessor { get; set; } public OrderProcessorDecorator(IOrderProcessor orderprocessor) { OrderProcessor = orderprocessor; } public void Submit(Order order) { PreProceed(order); OrderProcessor.Submit(order); PostProceed(order); } public void PreProceed(Order order) { Console.WriteLine("提交定单前,举行定单数据校验...."); if (order.Price 0) { Console.WriteLine("定单总价有误,请从新查对定单。"); } } public void PostProceed(Order order) { Console.WriteLine("提交带单后,举行定单日记纪录......"); Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "提交定单,定单称号:" + order.Name + ",定单价钱:" + order.Price); } }
挪用代码:
static void Main(string[] args) { Order order = new Order() { Id = 1, Name = "lee", Count = 10, Price = 100.00, Desc = "定单测试" }; IOrderProcessor orderprocessor = new OrderProcessorDecorator(new OrderProcessor()); orderprocessor.Submit(order); Console.ReadLine(); }
获得效果:
上面我们模仿定单提交的例子,在提交一个定单前,我们需要做很多的准备事情,比方数据有效性校验等;定单提交完成以后,我们还需要做日记纪录等。上面的代码很简朴,没有任何庞杂的逻辑,从上面的代码可以看出,我们经由过程静态植入的体式格局手动在实行要领前和实行要领后让它做一些我们需要的功用。AOP的完成道理应当也是云云,只不过它协助我们做了要领阻拦,帮我们省去了大批反复代码,我们要做的仅仅是写好阻拦前和阻拦后需要处置惩罚的逻辑。
2、动态代办
相识了静态阻拦的例子,你是不是对AOP有一个开端的认识了呢。下面我们就来究竟AOP该怎样运用。根据园子内里很多牛人的说法,AOP的完成体式格局大抵可以分为两类:动态代办和IL 编织两种体式格局。博主也不盘算照本宣科,分别拿Demo来措辞吧。下面就以两种体式格局各选一个代表框架来申明。
动态代办体式格局,博主就以微软企业库(MS Enterprise Library)内里的PIAB(Policy Injection Application Block)框架来作申明。
起首需要下载以下几个dll,然后增加它们的援用。
然后定义对应的Handler
public class User { public string Name { set; get; } public string PassWord { set; get; } } #region 1、定义特征轻易运用 public class LogHandlerAttribute : HandlerAttribute { public string LogInfo { set; get; } public int Order { get; set; } public override ICallHandler CreateHandler(IUnityContainer container) { return new LogHandler() { Order = this.Order, LogInfo = this.LogInfo }; } } #endregion #region 2、注册对需要的Handler阻拦要求 public class LogHandler : ICallHandler { public int Order { get; set; } public string LogInfo { set; get; } //这个要领就是阻拦的要领,可以规定在实行要领之前和以后的阻拦 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Console.WriteLine("LogInfo内容" + LogInfo); //0.剖析参数 var arrInputs = input.Inputs; if (arrInputs.Count > 0) { var oUserTest1 = arrInputs[0] as User; } //1.实行要领之前的阻拦 Console.WriteLine("要领实行前阻拦到了"); //2.实行要领 var messagereturn = getNext()(input, getNext); //3.实行要领以后的阻拦 Console.WriteLine("要领实行后阻拦到了"); return messagereturn; } } #endregion #region 3、用户定义接口和完成 public interface IUserOperation { void Test(User oUser); void Test2(User oUser, User oUser2); } //这里必需要继续这个类MarshalByRefObject,不然报错 public class UserOperation : MarshalByRefObject, IUserOperation { private static UserOperation oUserOpertion = null; public UserOperation() { //oUserOpertion = PolicyInjection.Create(); } //定义单例形式将PolicyInjection.Create()发作的这个对象传出去,如许就避免了在挪用途写这些东西 public static UserOperation GetInstance() { if (oUserOpertion == null) oUserOpertion = PolicyInjection.Create(); return oUserOpertion; } //挪用属性也会阻拦 public string Name { set; get; } //[LogHandler],在要领上面加这个特征,只对此要领阻拦 [LogHandler(LogInfo = "Test的日记为aaaaa")] public void Test(User oUser) { Console.WriteLine("Test要领实行了"); } [LogHandler(LogInfo = "Test2的日记为bbbbb")] public void Test2(User oUser, User oUser2) { Console.WriteLine("Test2要领实行了"); } } #endregion
末了我们来看挪用的代码:
static void Main(string[] args) { try { var oUserTest1 = new User() { Name = "test2222", PassWord = "yxj" }; var oUserTest2 = new User() { Name = "test3333", PassWord = "yxj" }; var oUser = UserOperation.GetInstance(); oUser.Test(oUserTest1); oUser.Test2(oUserTest1,oUserTest2); } catch (Exception ex) { //throw; } }
获得效果以下:
我们来看实行Test()要领和Test2()要领时刻的递次。
由于Test()和Test2()要领上面加了LogHander特征,这个特征内里定义了AOP的Handler,在实行Test和Test2要领之前和以后都邑进入Invoke()要领内里。实在这就是AOP的意义地点,将切面的通用功用在一致的处所处置惩罚,在重要逻辑内里直接用过特征运用即可。
3、IL编织
静态织入的体式格局博主盘算运用PostSharp来申明,一来这个运用起来简朴,二来项目中用过这类体式格局。
Postsharp从2.0版本就最先收费了。为了申明AOP的功用,博主下载了一个免费版本的装置包,运用PostSharp与别的框架不太一样的是一定要下载装置包装置,只援用类库是不可的,由于上文说过,AOP框架需要为编译器或运行时增加扩大。运用步骤以下:
(1)下载Postsharp装置包,装置。
(2)在需要运用AOP的项目中增加PostSharp.dll 这个dll的援用。
(3)定义阻拦的要领:
[Serializable] public class TestAop : PostSharp.Aspects.OnMethodBoundaryAspect { //发作非常时进入此要领 public override void OnException(MethodExecutionArgs args) { base.OnException(args); } //实行要领前实行此要领 public override void OnEntry(MethodExecutionArgs args) { base.OnEntry(args); } //实行要领后实行此要领 public override void OnExit(MethodExecutionArgs args) { base.OnExit(args); } }
注重这里的TestAop这个类必需如果可序列化的,所以要加上[Serializable]特征
(4)在需要阻拦功用的处所运用。
在类上面加特征阻拦,此类下面的一切的要领都邑具有阻拦功用。
[TestAop]public class Impc_TM_PLANT : Ifc_TM_PLANT { /// /// 猎取或设置效劳接口。 /// private Ic_TM_PLANTService service { get; set; } public IList Find() { DTO_TM_PLANT otest = null; otest.NAME_C = "test"; //非常,会进入OnException要领 return service.FindAll(); } }
要领上面加特征阻拦,只会阻拦此要领。
[TestAop] public IList Find() { DTO_TM_PLANT otest = null; otest.NAME_C = "test"; return service.FindAll(); }
有无觉得很简朴,很壮大,实在这一简朴运用,处理我们罕见的日记、非常、权限考证等功用几乎太小菜一碟了。固然Postsharp能够另有很多越发高等的功用,有兴致可以穷究下。
4、MVC内里的Filter
public class AOPFilterAttribute : ActionFilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { throw new System.NotImplementedException(); } public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); } public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); } }
在controller内里运用该特征:
[AOPFilter] public JsonResult GetEditModel(string strType) { var lstRes = new List>(); var lstResPage = new List(); //.........todo return Json(new { lstDataAttr = lstRes, PageAttr = lstResPage, lstJsConnections = lstJsPlumbLines }, JsonRequestBehavior.AllowGet); }
调试可知,在实行GetEditModel(string strType)要领之前,会先实行OnActionExecuting()要领,GetEditModel(string strType)以后,又会实行OnActionExecuted()要领。这在我们MVC内里权限考证、毛病页导向、日记纪录等经常使用功用都可以轻易处理。
以上就是C#进阶系列——AOP?AOP!的内容,更多相干内容请关注ki4网(www.ki4.cn)!