AOP_02 通过ContextBoundObject、ContextAttribute 上下文对象实现
主要用于 监听对象的标记
[AttributeUsage(AttributeTargets.Class)] public class AOPAttribute : ContextAttribute, IContributeObjectSink { // IContributeObjectSink :在远程处理调用的服务器端分配对象特定的侦听接收器, 这个地方监听到AOPAttribute标记的对象时,会执行GetObjectSink方法 public AOPAttribute() : base("Proxy") { } /// <summary> /// 获取上下文中的消息【方法】 /// </summary> /// <param name="obj"></param> /// <param name="nextSink"></param> /// <returns></returns> public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink) { return new MessageSink(nextSink); } }
主要 用于监听继承ContextBoundObject所有对象
/// <summary> /// 任何一个需要应用上下文同步机制类的父类, /// 继承ContextBoundObject的子类实例称为上下文绑定对象, /// 而通常的类实例称为上下文灵活对象。上下文绑定的对象永远在其上下文中执行 /// </summary> [AOP] // 这里[Aop] 表示,继承AOPIntercept 所有的子类都会被监听,也可以在子类中打【aop】标签 ContextBoundObject 和ContextAttribute 配合使用 public class AOPIntercept : ContextBoundObject { /* 通过ContextBoundObject来实现AOP, * 其中有大约60%的时间花在GetCustomAttribute的反射上, * 另外40%则是MarshalByRefObject(ContextBoundObject的基类, * 实际上ContextBoundObject什么事情都没做,只是单纯的继承了MarshalByRefObject) * 内部上下文管理上,它需要管理些啥呢?ContextBoundObject是一个上下文对象的基类 * ,继承自它的子类将被一个特别的上下文管理起来,这个上下文包括一系列的属性集合或者规则, * 当进入或者离开上下文时,将强制执行规则。当使用ContextBoundObject实现AOP时,除了性能底下, * 其必须继承自ContextBoundObject,对于单继承的语言来讲可能带来不便。 */ // 继承 ContextBoundObject的所有子类,都会获取到上下文信息, }
/// <summary> /// 监听消息 /// </summary> public class MessageSink : IMessageSink { // 添加两个委托,用于监听执行前和执行后的过程 public static event EventHandler<EventArgs> BeforeExcute; public static event EventHandler<EventArgs> AfterExcute; private IMessageSink _sink; public MessageSink(IMessageSink sink) { _sink = sink; } public IMessageSink NextSink => _sink; public IMessageCtrl AsyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg, IMessageSink replySink) { throw new NotImplementedException(); } /// <summary> /// 以同步方式处理给定的消息 /// </summary> /// <param name="msg"></param> /// <returns></returns> public System.Runtime.Remoting.Messaging.IMessage SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg) { if (BeforeExcute != null) BeforeExcute.Invoke(msg.Properties,null); var message= _sink.SyncProcessMessage(msg); // 执行方法,并返回msg if (AfterExcute != null) AfterExcute.Invoke(msg.Properties, null); return message; } }
使用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 代理 { class Program { static void Main(string[] args) { //IMessage message = new ProxyMessage(); //message.SendMessage("hnzheng"); // 注册监听 MessageSink.BeforeExcute += BeforeExcute; MessageSink.AfterExcute += AfterExcute; TestAop testAop = new TestAop(); testAop.TestMethod("1111"); Console.ReadLine(); } public static void BeforeExcute(object sender,EventArgs e) { Console.WriteLine(nameof(BeforeExcute)); } public static void AfterExcute(object sender, EventArgs e) { Console.WriteLine(nameof(AfterExcute)); } static void GetString(string name) { // GetString(name); } } [AOP] public class TestAop: AOPIntercept { public void TestMethod(string name) { Console.WriteLine(name); } } }
结果:
缺点:
/* 通过ContextBoundObject来实现AOP,
* 实际上ContextBoundObject什么事情都没做,只是单纯的继承了MarshalByRefObject)
* 内部上下文管理上,ContextBoundObject是一个上下文对象的基类
* ,继承自它的子类将被一个特别的上下文管理起来,这个上下文包括一系列的属性集合或者规则,
* 当进入或者离开上下文时,将强制执行规则。当使用ContextBoundObject实现AOP时,除了性能底下,
* 其必须继承自ContextBoundObject,对于单继承的语言来讲可能带来不便。
*/