簡介
若是你很熟悉面向方面編程(AOP),你就會知道給代碼增長「切面」可使代碼更清晰而且具備可維護性。可是AOP一般都依賴於第三方類庫或者硬編碼的.net特性來工做。雖然這些實現方式的好處大於它們的複雜程度,可是我仍然在尋找一種實現AOP的更爲簡單的方式,來試個人代碼更爲清晰。我將它們單獨移出來,並命名爲AspectF。
Aspect Oriented Programming (AOP)的背景
「切面」指的是那些在你寫的代碼中在項目的不一樣部分且有相同共性的東西。它多是你代碼中處理異常、記錄方法調用、時間處理、從新執行一些方法等等的一些特殊方式。若是你沒有使用任何面向切面編程的類庫來作這些事情,那麼在你的整個項目中將會遺留一些很簡單而又重複的代碼,它將使你的代碼很難維護。例如,在你的業務邏輯層有些方法須要被記錄,有些異常須要被處理,有些執行須要計時,數據庫操做須要重試等等。因此,也許你會寫出下面這樣的代碼。
攔截消息
public class AopAttribute : ProxyAttribute
{
public override MarshalByRefObject CreateInstance(Type serverType)
{
//AopProxy 就是攔截消息處理
AopProxy realProxy = new AopProxy(serverType);
return realProxy.GetTransparentProxy() as MarshalByRefObject;
}
}
處理消息
public class AopProxy : RealProxy
{
public AopProxy(Type serverType)
: base(serverType) { }
//攔截消息後的處理方法
public override IMessage Invoke(IMessage msg)
{
if (msg is IConstructionCallMessage) // 若是是構造函數,按原來的方式返回便可。
{
IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage;
IConstructionReturnMessage constructionReturnMessage =
this.InitializeServerObject((IConstructionCallMessage) msg);
RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue);
Console.WriteLine("Call constructor");
return constructionReturnMessage;
}
else //若是是方法調用(屬性也是方法調用的一種)
{
IMethodCallMessage callMsg = msg as IMethodCallMessage;
IMessage message;
try
{
object[] args = callMsg.Args;
//在這裏調用要實現的方法
object o = callMsg.MethodBase.Invoke(GetUnwrappedServer(), args);
message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg);
}
catch (Exception e)
{
message = new ReturnMessage(e, callMsg);
}
Console.WriteLine(message.Properties["__Return"].ToString());
return message;
}
}
}
調用的類
[AopAttribute]
public class AopClass : ContextBoundObject
{
public string Hello()
{
return "welcome";
}
public object GetName(string name)
{
return name + "說:此樹是我栽,此路是我開,要想今後過,把命留下來";
}
}
class Program
{
static void Main(string[] args)
{
AopClass ap=new AopClass();
int k = 1;
ap.Hello();
k++;
ap.GetName("donsgheng");
Console.WriteLine(k);
}
}