C# 通过Attribute实现AOP面向切面编程

/// <summary>
/// (使用示例)需要拦截插入代码的类,要绑定ContextBoundObject 上下文基类
/// </summary>
[AOPContext]
public class TestA : ContextBoundObject
{
    [AOPMethod]
    public string TestAsyncFunc(string param)
    {
        Thread.Sleep(1000);
        Console.WriteLine("DoSometing");
        return "complete";
    }
}


/// <summary>
/// 定义一个类特性,继承 ContextAttribute 特性、实现 IContributeObjectSink拦截接口
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class AOPContextAttribute : ContextAttribute, IContributeObjectSink
{

    public AOPContextAttribute() : base("AOPContext")
    {
    }

    /// <summary>
    /// 重写拦截处理
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="nextSink"></param>
    /// <returns></returns>
    public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
    {
        return new AOPHandler(nextSink);
    }
}

/// <summary>
/// 定义一个方法特性,用于区分该方法是否拦截,所以没有内容可以
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class AOPMethodAttribute : Attribute
{
}

/// <summary>
/// 实现消息接收器接口
/// </summary>
public class AOPHandler : IMessageSink
{
    /// <summary>
    /// 下一个消息接收器
    /// </summary>
    private readonly IMessageSink _nextSink;

    /// <summary>
    /// 构造函数
    /// </summary>
    public AOPHandler(IMessageSink nextSink)
    {
        _nextSink = nextSink;
    }

    public IMessageSink NextSink
    {
        get { return _nextSink; }
    }

    /// <summary>
    /// 同步处理方法  
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    public IMessage SyncProcessMessage(IMessage msg)
    {
        IMessage message = null;
        IMethodCallMessage callMessage = msg as IMethodCallMessage;
        // 判断方法是否拦截(判断方法有没有上面定义的 AOPMethodAttribute 特性)
        if (callMessage != null && (Attribute.GetCustomAttribute(callMessage.MethodBase, typeof(AOPMethodAttribute))) != null)
        {
            // 执行前
            PreProceed(msg);
            // invoke 执行原方法
            message = _nextSink.SyncProcessMessage(msg);
            // 执行后
            PostProceed(message);
        }
        else
        {
            message = _nextSink.SyncProcessMessage(msg);
        }
        return message;
    }

    /// <summary>
    /// 异步处理方法
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replySink"></param>
    /// <returns></returns>
    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
    {
        return null;
    }

    /// <summary>
    /// 方法执行前
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="before"></param>
    public void PreProceed(IMessage msg)
    {
        var message = msg as IMethodMessage;
        var typeName = message.TypeName.Split(',')[0];
        var methodName = message.MethodName;
        // 获取到的参数列表 object[]
        var paramss = message.Args;
        Console.WriteLine($"{typeName}类{methodName}方法执行前,入参为:{string.Join(",", paramss.ToArray())}");
        //System.Diagnostics.Debug.WriteLine($"{typeName}类{methodName}方法执行前,入参为:{string.Join(",", paramss.ToArray())}");//MVC调试的输出
    }

    /// <summary>
    /// 方法执行后
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="after"></param>
    public void PostProceed(IMessage msg)
    {
        var message = msg as IMethodReturnMessage;
        var typeName = message.TypeName.Split(',')[0];
        var methodName = message.MethodName;
        // 获取到的返回值
        var param = message.ReturnValue;
        Console.WriteLine($"{typeName}类{methodName}方法执行后,返参为:{param.ToString()}");
        //System.Diagnostics.Debug.WriteLine($"{typeName}类{methodName}方法执行后,返参为:{param.ToString()}");//MVC调试的输出
    }
}

结果输出为:

xxx类xxx方法执行前,入参为:111
DoSometing
xxx类xxx方法执行后,返参为:complete

参考文章:【C# / Pattern】C#中利用Attribute实现AOP(面向切面编程)_ls9512-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值