博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AOP 面向切面编程
阅读量:6957 次
发布时间:2019-06-27

本文共 3093 字,大约阅读时间需要 10 分钟。

有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程)

不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用.
以下是C#的AOP方法:

首先建立一个控制台工程

写一个calc类,里面有add个方法:

一会将拦截这个方法,对出参,入参进行检查.

public class Calc {    public int add(int a, int b) { return a + b; } } class Program { static void Main(string[] args) { Console.Title = ""; Console.WriteLine(new Calc().add(1, 0)); Console.WriteLine(new Calc().add(2, 3)); Console.WriteLine(new Calc().add(1, 1)); Console.ReadKey(true); } }

运行效果:

非常普通

接着添加一个文件

里面的代码:
首先写一个消息接收器类,用来处理拦截到的调用:

/// /// AOP方法处理类,实现了IMessageSink接口 ///  public sealed class MyAopHandler : IMessageSink { ///  /// 下一个接收器 ///  public IMessageSink NextSink { get; private set; } public MyAopHandler(IMessageSink nextSink) { this.NextSink = nextSink; } ///  /// 同步处理方法 ///  ///  /// 
public IMessage SyncProcessMessage(IMessage msg) { //方法调用消息接口 var call = msg as IMethodCallMessage; //只拦截指定方法,其它方法原样释放 if (call == null || (Attribute.GetCustomAttribute(call.MethodBase, typeof(AOPMethodAttribute))) == null || call.MethodName != "add") return NextSink.SyncProcessMessage(msg); //判断第2个参数,如果是0,则强行返回100,不调用方法了 if (((int)call.InArgs[1]) == 0) return new ReturnMessage(100, call.Args, call.ArgCount, call.LogicalCallContext, call); //判断第2个参数,如果是1,则参数强行改为50(失败了) //if (((int)call.InArgs[1]) == 1) call = new MyCall(call, call.Args[0], 50);//方法1 失败了 //if (((int)call.InArgs[1]) == 1) call.MethodBase.Invoke(GetUnwrappedServer(), new object[] { call.Args[0], 50 });//方法2 (无法凑够参数) var retMsg = NextSink.SyncProcessMessage(call); //判断返回值,如果是5,则强行改为500 if (((int)(retMsg as IMethodReturnMessage).ReturnValue) == 5) return new ReturnMessage(500, call.Args, call.ArgCount, call.LogicalCallContext, call); return retMsg; } /// /// 异步处理方法(暂不处理) /// /// /// ///
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) => null; }

然后声明两个特性,用来指明我们要拦截的Methot,以及它所在的Class:

/// /// 贴在方法上的标签 ///  [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public sealed class AOPMethodAttribute : Attribute { } ///  /// 贴在类上的标签 ///  [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] public sealed class AOPAttribute : ContextAttribute, IContributeObjectSink { public AOPAttribute() : base("AOP") { } ///  /// 实现消息接收器接口 ///  ///  ///  /// 
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next) => new MyAopHandler(next); }

回到Calc类,给类和Methot加上特性标签:

[AOP]public class Calc : ContextBoundObject { [AOPMethod] public int add(int a, int b) { return a + b; } }

运行,效果如下:

可以看到返回值已经被拦截修改处理过了

试一下继承:

[AOP]public class Calc : ContextBoundObject { [AOPMethod] public virtual int add(int a, int b) { return a + b; } } public class Calc2 : Calc { public override int add(int a, int b) { return a + b; } } class Program { static void Main(string[] args) { Console.Title = ""; Console.WriteLine(new Calc2().add(1, 0)); Console.WriteLine(new Calc2().add(2, 3)); Console.WriteLine(new Calc2().add(1, 1)); Console.ReadKey(true); } }

运行效果:

至此AOP的介绍结束,不过有一点很遗憾,无法修改参数,找了一下午资料无结果,如果谁知道怎么操作能否回复告知一下?

原创文章,转载请注明来源. http://www.cnblogs.com/DragonStart/
 
 
你可能感兴趣的文章
love2d教程13--图形界面
查看>>
POJ 1276 Cash Machine
查看>>
C语言中 struct成员变量顺序对内存的占用
查看>>
POJ1291-并查集/dfs
查看>>
移动办公首选!电商热卖轻薄本高低该怎么选?
查看>>
[译] RNN 循环神经网络系列 1:基本 RNN 与 CHAR-RNN
查看>>
Android技能树 — PopupWindow小结
查看>>
如何在create-react-app项目中使用vw实现手淘vw移动端适配布局
查看>>
Wormhole燃烧地址到底有多安全
查看>>
Web探索之旅 | 第三部分第三课:协议
查看>>
20个优秀手机界面扁平化设计,让你一秒看懂扁平化
查看>>
从百度的PPT文化看程序员晋升
查看>>
Python测试登录功能
查看>>
mysql 创建高性能索引
查看>>
babel插件入门-AST(抽象语法树)
查看>>
分布式ID
查看>>
原声写法操作table
查看>>
10 分钟内快速构建能够承载海量数据的 nginx 日志分析与报警平台
查看>>
完全二叉树实现优先队列与堆排序
查看>>
启动时间知多少?8款音视频类应用测评报告分析
查看>>