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)
{
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 的两个方法都进行了拦截和输出。
评论区