C# 使用Emit实现动态AOP框架 (二)
实现DynamicProxy前,先介绍几个必要的辅助类:
一、切面上下文类AspectContext
该类是作为切面特性类的OnEntry和OnEixt方法的参数用的,该类包含了被代理对象Sender、当前切入的方法名称(Name)、调用方法的参数列表(Args)以及返回值(Result)
1 public class AspectContext 2 { 3 4 #region 构造函数 5 /// <summary> 6 /// 构造函数 7 /// </summary> 8 /// <param name="sender">被切入的对象</param> 9 /// <param name="name">切入方法名称</param> 10 /// <param name="args">调用参数</param> 11 public AspectContext(object sender, string name, object[] args) 12 { 13 Sender = sender; Name = name; Args = args; Result = null; 14 } 15 #endregion 16 17 #region 属性 18 19 /// <summary> 20 /// 被切入的对象 21 /// </summary> 22 public object Sender { get; set; } 23 24 /// <summary> 25 ///切入方法名称 26 /// </summary> 27 public string Name { get; set; } 28 29 /// <summary> 30 /// 方法调用参数 31 /// </summary> 32 public object[] Args { get; set; } 33 34 /// <summary> 35 /// 返回值 36 /// </summary> 37 public object Result { get; set; } 38 39 #endregion 40 }
二、切面特性基类 AspectAttribute
/// <summary> /// 切面特性基类 /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property)] public abstract class AspectAttribute : Attribute { public AspectAttribute() { IntercepType = XAOP.IntercepType.All; } public abstract InterceptType InterceptType { get; set; } public abstract void OnEntry(AspectContext context); public abstract void OnExit(AspectContext context); }
该类作为所有切面特性的基类,包含拦截的类型、方法调用入口和方法调用出口。
三、拦截类型 InterceptType
/// <summary> /// 拦截类型 /// </summary> public enum InterceptType { #region 枚举值 /// <summary> /// 入口 /// </summary> OnEntry = 1, /// <summary> /// 出口 /// </summary> OnExit = 2, /// <summary> /// 所有 /// </summary> All = 3 #endregion }
四、日志特性类
该类简单实现了方法调用前后的日志记录功能。
/// <summary> /// 日志特性 /// </summary> public class LogAttribute : AspectAttribute { public override InterceptType InterceptType { get; set; } #region 开始调用 /// <summary> /// 开始调用 /// </summary> /// <param name="context"></param> public override void OnEntry(AspectContext context) { Console.Write("Log OnEntry:"); if (context != null && context.Args != null) Console.WriteLine("{0}({1})", context.Name, string.Join(",", context.Args)); } #endregion #region 调用结束 /// <summary> /// /// </summary> /// <param name="context"></param> public override void OnExit(AspectContext context) { Console.WriteLine("Log OnExit: " + context.Name + (context.Result != null ? " Result: " + context.Result.ToString() : "") + "\r\n"); } #endregion }