先說下場景,c#中為什麼要使用aop,而我又是在哪裡使用aop?
本人隻是想攔截實體類的set的方法,然後在set之前,調用一下其它方法,把值賦給另一個對象。
而我做的都是在實體類的基類裡處理:
比如:
如果說,我這樣實作:在ormbase中可以提供方法,讓所有的子類的屬性都這樣操作:

public class users:ormbase
{
public int _id;
public int id
get;
set
base.setxx(value);
}
}

不過每個實體都這樣寫,雖然是啥沒問題,不過能簡化的還是簡化。
在能追求簡潔的世界裡,當然更喜歡簡潔的寫法如:
public int id {get;set;}
是以,直接在基類裡直接攔截子類set方法,在裡面直接調用setxx就搞定了,如何實作呢?又花了一天的時間查資料研究學習并實作。
為此,要攔截,就得折騰aop:
傳統的aop使用realproxy,使用非常簡單,但是被忽悠的非常複雜,下面:
1:在要攔截的類頭上加個屬性辨別,同時繼承自contextboundobject:
[aopattribute]
public class ormbase:contextboundobject
ok,在基類裡加一個,這樣所有子類也算被附加了,加上一個辨別,就可以被攔截了,那這個aopattribute屬性是啥?看下面
2:aopattribute繼承代理屬性辨別類,用來挂在要攔截的類的頭上:

class aopattribute : proxyattribute
{
public override marshalbyrefobject createinstance(type servertype)
{
aopproxy realproxy = new aopproxy(servertype);
return realproxy.gettransparentproxy() as marshalbyrefobject;
}
}

看,裡面就兩行,非常簡單,中間調用了繼承realproxy的aopproxy類,aopproxy是什麼,怎麼出來的?看下面
3:aopproxy類,就是攔截的消息處理,先上個簡單版,免的大夥看不懂:

class aopproxy : realproxy
public aopproxy(type servertype)
: base(servertype)
public override imessage invoke(imessage msg)
//消息攔截之後,就會執行這裡的方法。

ok,簡單吧,就這麼兩個類,就可以實作攔截了,不過重點就是這裡攔截之後的代碼,稍為複雜點,一般照抄就行了,攔截的代碼如下:

if (msg is iconstructioncallmessage) // 如果是構造函數,按原來的方式傳回即可。
{
iconstructioncallmessage constructcallmsg = msg as iconstructioncallmessage;
iconstructionreturnmessage constructionreturnmessage = this.initializeserverobject((iconstructioncallmessage)msg);
realproxy.setstubdata(this, constructionreturnmessage.returnvalue);
return constructionreturnmessage;
}
else if (msg is imethodcallmessage) //如果是方法調用(屬性也是方法調用的一種)
imethodcallmessage callmsg = msg as imethodcallmessage;
object[] args = callmsg.args;
imessage message;
try
{
if (callmsg.methodname.startswith("set_") && args.length == 1)
{
//這裡檢測到是set方法,然後應怎麼調用對象的其它方法呢?
}
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);
return message;
return msg;

為了調用原始對象的其它方法,我花了近一天的時間查資料,可惜網絡上并沒有相應的資訊,多數的人應用,都是引向一個其它方法(一個不需要調用原始對象的方法)
目前網絡上aop資訊太少,c#的更少,關于如何擷取原始對象,然後調用原始對象的,找不到一篇相關文章,我特糾結。
于是,我按傳統方式,想盡辦法的想擷取到原始對象,再調用,經過九九八十一招,還是失敗了。
(一開始是想:通過反射從類型再建立一個實體這種不靠譜的嘗試: 造成死循環,每次new攔截,在攔截裡又new)
中間省一大堆......痛苦的經曆和嘗試.......
隻要用心想,方法總有的,最終還是被我發現了:
1:擷取要調用的方法:
在構造函數中,根據傳進來的servertype,擷取到setxx的方法methodinfo:
method = servertype.getmethod("setxx", bindingflags.nonpublic | bindingflags.instance);
2:在攔截方法中調用:

if (callmsg.methodname.startswith("set_") && args.length == 1)
method.invoke(getunwrappedserver(), new object[] { callmsg.methodname.substring(4), args[0] });//對屬性進行調用
}

過程很複雜,嘗試過n百種方式,結果很簡單,分享很重要!
為此,解決了orm對子類的屬性攔截,并實作了在屬性指派時調用執行個體其它方法。