• C#中如何使用MethodDecorator插件实现AOP
  • 发布于 2个月前
  • 270 热度
    0 评论
  • 风尘客
  • 0 粉丝 32 篇博客
  •   
AOP
MethodDecorator 是一个 Fody 的插件,我们可以通过这个组件,非常简单方便地在 C# 中实现 AOP。Aspect Oriented Programming 面向切面编程。解耦是程序员编码开发过程中一直追求的。AOP也是为了解耦所诞生。

如何使用
首先需要通过 Nuget 安装 MethodDecorator.Fody,如下:
PM> Install-Package Fody
PM> Install-Package MethodDecorator.Fody
接下来,手动添加一个 InterceptorAttribute 特性,需要继承IMethodDecorator 接口,实现 Init, OnEntry, OnExit, OnException 方法,完整代码如下:
[module: Interceptor]
namespace ConsoleApp5
{  
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class)]
    public class InterceptorAttribute : Attribute, IMethodDecorator
    { 
        public void Init(object instance, MethodBase method, object[] args)
        {
            // 堆代码 duidaima.com
            Console.WriteLine(string.Format("初始化: {0} [{1}]", method.DeclaringType.FullName + "." + method.Name, args.Length));
        }

        public void OnEntry()
        {
            Console.WriteLine("方法进入");
        }
        public void OnExit()
        {
            Console.WriteLine("方法退出");
        }
        public void OnException(Exception exception)
        {
            Console.WriteLine(string.Format("执行异常: {0}: {1}", exception.GetType(), exception.Message));
        }
    }  
}
创建一个 Sample 类,包含了一个输出字符串的 Hello 方法,然后在方法上加上刚刚创建的 Interceptor 特性。
public class Sample
{
    [Interceptor]
    public void Hello()
    {
        Console.WriteLine("Hello");
    } 
}
运行程序,可以看到方法执行前后都已经输出了我们添加的埋点信息:
using ConsoleApp5;
var sample = new Sample();
sample.Hello();
Console.ReadKey(); 

是不是非常简单!
使用 MethodDecorator.Fody 后,最终会编译成类似下面的代码:
public class Sample {
    public void Hello(int value) {
        InterceptorAttribute attribute =
            (InterceptorAttribute) Activator.CreateInstance(typeof(InterceptorAttribute));
        MethodBase method = MethodBase.GetMethodFromHandle(__methodref (Sample.Hello), __typeref (Sample));
        object[] args = new object[1] { (object) value };
        attribute.Init((object)this, method, args);
        attribute.OnEntry();
        try {
            Console.WriteLine("Hello");
            attribute.OnExit();
        }
        catch (Exception exception) {
            attribute.OnException(exception);
            throw;
        }
    }
}
还可以把 Interceptor 特性添加到 Class 上,对所有的方法进行拦截,修改代码如下:
using ConsoleApp5;
var sample = new Sample();
sample.Hello();
sample.World();
Console.ReadKey(); 

[Interceptor]
public class Sample
{
    public void Hello()
    {
        Console.WriteLine("Hello");
    }     
    public void World()
    {
        Console.WriteLine("World");
    } 
}

可以看到, Sample 的两个方法都进行了拦截和输出。

用户评论