这一段时间对AOP很感兴趣,但由于.net下没有类似AspectJ之类的成熟AOP框架,很是不爽。前两天在v192(魔渡众生) 兄的指点下找到了websharp的网站,上面作者提到了在.net下实现AOP的三种方法:
------------------------------------------------------------
1.使用ContextAttribute和ContextBoundObject来对对象的方法进行拦截。关于ContextAttribute的具体使用方法,读者可以参考MSDN等相关资料。
2.使用Emit来,在运行时刻动态构建被织入代码后的类,当程序调用被织入类时,实际上调用的是被修改后的类。LOOM使用的就是这种方式,但是,个人认为,LOOM目前的实现非常生硬,其可扩展性和灵活性都不是很好。
3.使用Proxy模式。这也是本文将详细介绍的方法。(websharp实现的思路)
-----------------------------------------------------------------
小弟一时很有启发,便动手用第一种思路实现了一个简单的AOP试验程序,觉得还不错,但美中不足的是这种思路要求要做AOP“切片”的类必须从ContextBoundObject继承。
查看了一下websharp的使用示例,发现他也要求类必须从AspectObject继承,从使用的角度上来说,和第一种思路没什么不同。
这样就要求在设计系统的时候必须要对系统将来可能用到的关注方面有一个规划,在关注纵向系统结构时一样要同时关注横向系统结构。 一旦要加入新的方面,就必须对程序逻辑作较大修改(可能要修改类的继承关系),这样一来AOP比起传统的面向对象思路的优势好像就不那么明显了.
我也不太喜欢第二种AOP实现思路,但又实在想不出还有什么更好的方法。
请各位答疑解惑。
另:websharp的代码我还没看,不知道是不是用RealProxy类实现的代理?
------------------------------------------------------------
1.使用ContextAttribute和ContextBoundObject来对对象的方法进行拦截。关于ContextAttribute的具体使用方法,读者可以参考MSDN等相关资料。
2.使用Emit来,在运行时刻动态构建被织入代码后的类,当程序调用被织入类时,实际上调用的是被修改后的类。LOOM使用的就是这种方式,但是,个人认为,LOOM目前的实现非常生硬,其可扩展性和灵活性都不是很好。
3.使用Proxy模式。这也是本文将详细介绍的方法。(websharp实现的思路)
-----------------------------------------------------------------
小弟一时很有启发,便动手用第一种思路实现了一个简单的AOP试验程序,觉得还不错,但美中不足的是这种思路要求要做AOP“切片”的类必须从ContextBoundObject继承。
查看了一下websharp的使用示例,发现他也要求类必须从AspectObject继承,从使用的角度上来说,和第一种思路没什么不同。
这样就要求在设计系统的时候必须要对系统将来可能用到的关注方面有一个规划,在关注纵向系统结构时一样要同时关注横向系统结构。 一旦要加入新的方面,就必须对程序逻辑作较大修改(可能要修改类的继承关系),这样一来AOP比起传统的面向对象思路的优势好像就不那么明显了.
我也不太喜欢第二种AOP实现思路,但又实在想不出还有什么更好的方法。
请各位答疑解惑。
另:websharp的代码我还没看,不知道是不是用RealProxy类实现的代理?
按这个说法,1、3种做法都不能满足条件,因为虽然不用事先指定那些方法能够作为切入点,但你的切入点只能在事先想好的范围内选取,基本上也可以说是要“定义切入点”。
using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;namespace AOPTest
{
class CAspectCutter : IMessageSink
{
private IMessageSink m_ifcNext;
public CAspectCutter(MarshalByRefObject o, IMessageSink next)
{
m_ifcNext = next; } public IMessageSink NextSink
{
get
{
return m_ifcNext;
}
}
public IMessage SyncProcessMessage(IMessage msg)
{
Preprocess(msg);
IMessage returnMethod = m_ifcNext.SyncProcessMessage(msg);
PostProcess(msg, returnMethod);
return returnMethod;
}
public IMessageCtrl AsyncProcessMessage( IMessage msg, IMessageSink replySink )
{
throw new Exception("no AsyncProcessMessage");
} private void Preprocess(IMessage msg)
{
if (!(msg is IMethodMessage))
{
return;
} System.Console.WriteLine("-----------------------");
System.Console.WriteLine("preprocess"); IMethodMessage ifcMsg = msg as IMethodMessage;
Console.WriteLine(ifcMsg.MethodName + "("); for (int i = 0; i < ifcMsg.ArgCount; ++i)
{
System.Console.WriteLine(" " + ifcMsg.GetArgName(i) + "=" + ifcMsg.GetArg(i));
}
System.Console.WriteLine(" )"); }
private void PostProcess(IMessage msg, IMessage msgReturn)
{
if (!((msg is IMethodMessage) && (msgReturn is IMethodReturnMessage)))
{
return;
} System.Console.WriteLine("postProcessing: ");
IMethodReturnMessage ifcRet = msgReturn as IMethodReturnMessage;
if (ifcRet.ReturnValue != null)
{
System.Console.WriteLine(ifcRet.MethodName + " return :" + ifcRet.ReturnValue.ToString());
}
System.Console.WriteLine("===========================");
}
} public class CCutterContextProp : IContextProperty, IContributeObjectSink
{
public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
{
return new CAspectCutter(o, next);
}
public bool IsNewContextOK( Context newCtx )
{
return true ;
}
public void Freeze(Context newContext)
{
} public string Name
{
get
{
return "CCutterContextProp";
}
}
} [AttributeUsage(AttributeTargets.Class)]
public class CCutterAttb : ContextAttribute
{
public CCutterAttb(string sName) : base(sName) {}
public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
{
ccm.ContextProperties.Add(new CCutterContextProp());
}
}
[CCutterAttb("AOPTest")]
public class CAOPTest : ContextBoundObject
{
public string say(string s)
{
System.Console.WriteLine("in say method: say something");
return s;
}
public string doTest()
{
System.Console.WriteLine("woodhead is as woodhead does");
return "do nothing";
} public void returnNone(int x)
{
System.Console.WriteLine("return non, recv:" + x.ToString());
}
}
public class CDoTest
{
public static void Main()
{
CAOPTest at = new CAOPTest(); System.Console.WriteLine(at.say("test say"));
System.Console.WriteLine(at.doTest());
at.returnNone(99); System.Console.ReadLine();
}
}
}
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;namespace AOPTest
{
class CAspectCutter : IMessageSink
{
private IMessageSink m_ifcNext;
public CAspectCutter(MarshalByRefObject o, IMessageSink next)
{
m_ifcNext = next; } public IMessageSink NextSink
{
get
{
return m_ifcNext;
}
}
public IMessage SyncProcessMessage(IMessage msg)
{
Preprocess(msg);
IMessage returnMethod = m_ifcNext.SyncProcessMessage(msg);
PostProcess(msg, returnMethod);
return returnMethod;
}
public IMessageCtrl AsyncProcessMessage( IMessage msg, IMessageSink replySink )
{
throw new Exception("no AsyncProcessMessage");
} private void Preprocess(IMessage msg)
{
if (!(msg is IMethodMessage))
{
return;
} System.Console.WriteLine("-----------------------");
System.Console.WriteLine("preprocess"); IMethodMessage ifcMsg = msg as IMethodMessage;
Console.WriteLine(ifcMsg.MethodName + "("); for (int i = 0; i < ifcMsg.ArgCount; ++i)
{
System.Console.WriteLine(" " + ifcMsg.GetArgName(i) + "=" + ifcMsg.GetArg(i));
}
System.Console.WriteLine(" )"); }
private void PostProcess(IMessage msg, IMessage msgReturn)
{
if (!((msg is IMethodMessage) && (msgReturn is IMethodReturnMessage)))
{
return;
} System.Console.WriteLine("postProcessing: ");
IMethodReturnMessage ifcRet = msgReturn as IMethodReturnMessage;
if (ifcRet.ReturnValue != null)
{
System.Console.WriteLine(ifcRet.MethodName + " return :" + ifcRet.ReturnValue.ToString());
}
System.Console.WriteLine("===========================");
}
} public class CCutterContextProp : IContextProperty, IContributeObjectSink
{
public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
{
return new CAspectCutter(o, next);
}
public bool IsNewContextOK( Context newCtx )
{
return true ;
}
public void Freeze(Context newContext)
{
} public string Name
{
get
{
return "CCutterContextProp";
}
}
} [AttributeUsage(AttributeTargets.Class)]
public class CCutterAttb : ContextAttribute
{
public CCutterAttb(string sName) : base(sName) {}
public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
{
ccm.ContextProperties.Add(new CCutterContextProp());
}
}
[CCutterAttb("AOPTest")]
public class CAOPTest : ContextBoundObject
{
public string say(string s)
{
System.Console.WriteLine("in say method: say something");
return s;
}
public string doTest()
{
System.Console.WriteLine("woodhead is as woodhead does");
return "do nothing";
} public void returnNone(int x)
{
System.Console.WriteLine("return non, recv:" + x.ToString());
}
}
public class CDoTest
{
public static void Main()
{
CAOPTest at = new CAOPTest(); System.Console.WriteLine(at.say("test say"));
System.Console.WriteLine(at.doTest());
at.returnNone(99); System.Console.ReadLine();
}
}
}