C# AOP 面向切面编程之 调用拦截

有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程)
不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用.
以下是C#的AOP方法:

首先建立一个控制台工程

481370-20171027141749133-1193500127.png

写一个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);
    }
}

运行效果:
481370-20171027143106523-200888189.png
非常普通

接着添加一个文件

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

/// <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);
}

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

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

运行,效果如下:

481370-20171027165453617-934526172.png
可以看到返回值已经被拦截修改处理过了

试一下继承:

[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);
    }
}

运行效果:

481370-20171027170134867-1412588680.png

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

转载于:https://www.cnblogs.com/DragonStart/p/7744202.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值