Interception in. Net-a simple AOP framework Learning

Source: Internet
Author: User
Tags emit

Recently I accidentally discovered an interception implementation when I flipped through the DLL file at hand. This framework is much simpler than the currently popular AOP framework, but better reflects it. net.

Interception in. Net unity2.0 is implemented in three ways:

1. transparentproxy/realproxy interceptor is the remoting proxy mechanism.

2. Interface interceptor is dynamicCode(Emit programming) Implementation

3. Virtual method interceptor is also a dynamic code implementation. emit programming is basically similar to Il programming.

It should be noted that after the atatmethodinterceptor is used, policyinjectionbehavior will be ignored, and the obtained through resovle will always inherit the subclass instance of the intercepted class.
After all the matching policies are removed (policy, this class does not need to be intercepted), resolve returns the original class (non-proxy class)

 

 

Instance interception and type Interception

1. instance Interception

Transparentproxy and interface interceptor are instance interceptions. The so-called instance interception means that the intercepted objects exist completely and independently in the internal reference. The client communicates with the intercepted object through the proxy class (method call ).

2. Type Interception

The virtual method is a type blocking method. The internal reference does not contain instances of the intercepted type. The interception framework generates subtypes of the intercepted type through dynamic code.ProgramAfter the Assembly is loaded, the corresponding child type is instantiated in the memory to communicate with the client.

 

The following code implements the DLL in the post of transparentproxy/realproxy and interface interceptor.

1. transparentproxy/realproxy implementation

Using system. reflection; using system. runtime. remoting. proxies; using system. runtime. remoting. messaging; using system. runtime. remoting; internal class transparentproxy: realproxy {// fields private readonly implements albyrefobject m_target; // Methods public transparentproxy (implements albyrefobject target): Base (target. getType () {This. m_target = target;} public static object getproxy (marshalbyrefobject Target) {transparentproxy proxy = new transparentproxy (target); Return proxy. gettransparentproxy ();} public override iMessage invoke (iMessage MSG) {iMessage message = NULL; imethodcallmessage callmsg = MSG as imethodcallmessage; If (callmsg! = NULL) {object [] customattributes = callmsg. methodbase. getcustomattributes (true); this. invokebeforeattribute (customattributes, callmsg); try {message = remotingservices. executemessage (this. m_target, callmsg);} catch (exception) {This. invokeexceptionattribute (customattributes, callmsg, exception); throw;} This. invokeafterattribute (customattributes, callmsg, (returnmessage) message ). returnvalue);} return message ;}//.......... //............}

the class transproxyproxy maintains a reference to the target class instance (must be a subclass of the externalbyrefobject type). The final method call will reach the target instance through the message mechanism -- Statement remotingservices. executemessage (this. m_target, callmsg); invokebeforeattribute is called before the target method of the target object is called. If an error occurs, invokeexceptionattribute is called, and invokeafterattribute . note that in unity2.0 interception, the interceptionbehavior to be called is constructed into a pipeline model. During programming, the SCOP-like open and closed structure is displayed. This is only an ordered call, which needs to be differentiated . Invokebeforeattribute and other methods are implemented as follows

Private void invokeafterattribute (object [] attributes, imethodcallmessage callmsg, object result) {foreach (Object obj2 in attributes) {afterattribute attribute = obj2 as afterattribute; If (attribute! = NULL) {attribute. invoke (this. m_target, callmsg. methodbase, callmsg. inargs, result) ;}}list <iinterception> interceptionlist = proxybuilder. getinterceptionlist (this. m_target.gettype (). fullname + ". "+ callmsg. methodname, interceptiontype. after); If (interceptionlist! = NULL) {foreach (iinterception interception in interceptionlist) {interception. Invoke (this. m_target, callmsg. methodbase, callmsg. inargs, result );}}}

2. Interface interceptor code

Public static object getproxyinstance (object target, type interfacetype) {return activator. createinstance (getproxytype (target. getType (), interfacetype), new object [] {target, interfacetype});} Private Static type getproxytype (type targettype, type interfacetype) {appdomain domain = thread. getdomain (); assemblyname name = new assemblyname (); Name. name = "tempassemblyinjection"; assemblyname Nam E2 = Name; assemblybuilder = domain. definedynamicassembly (name2, assemblybuilderaccess. run); modulebuilder builder = assemblybuilder. definedynamicmodule ("tempclassinjection"); Type type = builder. getType ("tempassemblyinjection _ proxy" + interfacetype. name + targettype. name); If (type! = NULL) {return type;} m_typebuilder = builder. definetype ("tempassemblyinjection _ proxy" + interfacetype. name + targettype. name, typeattributes. public, targettype. basetype, new type [] {interfacetype}); m_target = m_typebuilder.definefield ("target", interfacetype, fieldattributes. private); m_interface = m_typebuilder.definefield ("iface", typeof (type), fieldattributes. private); createconstructor (m_typebuilder, m_target, m_interface); foreach (methodinfo info in interfacetype. getmethods () {createproxymethod (Info, m_typebuilder);} return m_typebuilder.createtype ();}

The code above uses emit programming to dynamically build an Assembly. The Assembly includes a proxy class to the target class. The proxy method is created one by one for the method signature in the given interface -- Statement createproxymethod (Info, m_typebuilder );
In addition, we can see that the proxy-type assembly is created only at the first access.
-- Statement
Type type = builder. GetType ("tempassemblyinjection _ proxy" + interfacetype. Name + targettype. Name );
If (type! = NULL)
{
Return type;
}

The created proxy class definition is similar to the following code:

Public class tempassemblyinjection _ proxyianimaldog: ianimal {// fields private type iface; private ianimal target; // Methods public tempassemblyinjection _ proxyianimaldog (Object obj1, type type1) {this.tar get = (ianimal) obj1; this. iface = type1;} public override int run (INT num1, int num2) {object [] parameters = new object [] {num1, num2}; Return (INT) dynamicproxy.intercepthandler(this.tar get,
Helper.getmethodfromtype(this.tar get. GetType (), methodbase. getcurrentmethod ()),
Parameters,
Helper. aspectunion (helper. getmethodfromtype (this. iface, methodbase. getcurrentmethod (). getcustomattributes (typeof (aspectattribute), true ))
);}}

Dynamicproxy. intercepthandler code

Public static object intercepthandlermethod (object target, methodbase method, object [] parameters, aspectattribute [] attributes) {object obj2; foreach (aspectattribute attribute in attributes) {If (attribute is beforeattribute) {attribute. invoke (target, method, parameters, null) ;}} foreach (iinterception interception in proxybuilder. getinterceptionlist (target. getType (). fullname + ". "+ method. name, interceptiontype. before) {interception. invoke (target, method, parameters, null);} Try {obj2 = target. getType (). getmethod (method. name ). invoke (target, parameters);} catch (exception) {foreach (aspectattribute attribute2 in attributes) {If (attribute2 is exceptionattribute) {attribute2.invoke (target, method, parameters, exception);} foreach (iinterception interception2 in proxybuilder. getinterceptionlist (target. getType (). fullname + ". "+ method. name, interceptiontype. exception) {interception2.invoke (target, method, parameters, exception);} Throw;} foreach (aspectattribute attribute3 in attributes) {If (attribute3 is afterattribute) {attribute3.invoke (target, method, method, parameters, obj2) ;}} foreach (iinterception interception3 in proxybuilder. getinterceptionlist (target. getType (). fullname + ". "+ method. name, interceptiontype. after) {interception3.invoke (target, method, parameters, obj2);} return obj2;} // properties public static callback intercepthandler {get {return New callback (dynamicproxy. intercepthandlermethod );}}

Download the demo package to complete the code and use the demo.

========================================Click here to download======================================

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.