有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程)
不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用.
以下是C#的AOP方法:
一会将拦截这个方法,对出参,入参进行检查.
- 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);
- }
- }
运行效果:
非常普通
里面的代码:
首先写一个消息接收器类,用来处理拦截到的调用:
- /// <summary>
- /// AOP方法处理类,实现了IMessageSink接口
- /// </summary>
- public sealed class MyAopHandler: IMessageSink {
- /// <summary>
- /// 下一个接收器
- /// </summary>
- public IMessageSink NextSink {
- get;
- private set;
- }
- public MyAopHandler(IMessageSink nextSink) {
- this.NextSink = nextSink;
- }
- /// <summary>
- /// 同步处理方法
- /// </summary>
- /// <param name="msg"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 异步处理方法(暂不处理)
- /// </summary>
- /// <param name="msg"></param>
- /// <param name="replySink"></param>
- /// <returns></returns>
- public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink) = >null;
- }
然后声明两个特性,用来指明我们要拦截的Methot,以及它所在的Class:
- /// <summary>
- /// 贴在方法上的标签
- /// </summary>
- [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
- public sealed class AOPMethodAttribute : Attribute { }
- /// <summary>
- /// 贴在类上的标签
- /// </summary>
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
- public sealed class AOPAttribute : ContextAttribute, IContributeObjectSink
- {
- public AOPAttribute() : base("AOP") { }
- /// <summary>
- /// 实现消息接收器接口
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="next"></param>
- /// <returns></returns>
- public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next) => new MyAopHandler(next);
- }
- [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);
- }
- }
来源: http://www.cnblogs.com/DragonStart/p/7744202.html