Continuation of the previous article: self-realization of the Simple AOP (a) Introduction
In the first article, a brief introduction to how AOP is implemented. Next, introduce attribute to specify the enhancement object for the method, thus implementing a simple AOP.
Note: The specified is an enhanced object, "object", that is, the attribute tag, which is actually an object. This allows you to easily implement enhanced extensions by using polymorphism.
Custom attribute
/// <summary> ///the enhanced object specified for the method tag/// <para>specified enhancements, which can be woven into the proxy delayproxy</para> /// </summary>[AttributeUsage (AttributeTargets.Method, inherited =false, AllowMultiple =false)] Public Sealed classAdviceattribute:attribute {/// <summary> ///Enhanced Objects/// </summary> PublicAdviceabstract Advice {Get;Private Set; } /// <summary> ///Use the default enhanced object of the specified type/// <para>If the type is empty, no enhancements are used</para> /// </summary> /// <param name= "type" ></param> Publicadviceattribute (Type type): This(Type,string. Empty) {}/// <summary> ///to initialize an enhanced object of the specified type using the public static method name/// <para>If the type is empty, no enhancements are used</para> /// </summary> /// <param name= "type" >type</param> /// <param name= "MethodName" > ///public static method name/// <para>If the method name is empty, call the default constructor</para> /// </param> PublicAdviceattribute (Type type,stringmethodName) { //If the type is empty, no enhancements are used if(Type = =NULL) { This. Advice =NULL; return; } if(string. Isnullorwhitespace (MethodName)) { This. Advice = Activator.CreateInstance (type) asadviceabstract; return; } This. Advice =type. InvokeMember (MethodName, System.Reflection.BindingFlags.InvokeMethod|System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static,NULL,NULL,NULL) asadviceabstract; } #regionThe following two ways are not very good, not recommended, so the privatization of the construction function/// <summary> ///to initialize an enhanced object of the specified type using a parameter list/// </summary> /// <param name= "type" >type</param> /// <param name= "Objs" >parameter list</param> PrivateAdviceattribute (Type type,params Object[] objs) { This. Advice = Activator.CreateInstance (type, OBJS) asadviceabstract; } /// <summary> ///to initialize an enhanced object of the specified type with a named parameter/// </summary> /// <param name= "Namedparameter" > ///named parameter list for formal parameters separated by colons and semicolons/// <para>supported data types are: string, int, bool, and types that can be deserialized by the static method parse</para> /// </param> /// <param name= "type" ></param> PrivateAdviceattribute (stringnamedparameter, type type) { This. Advice = Reflectionutil.invokeconstructor (type, namedparameter) asadviceabstract; } #endregion }
Attribute
Enhanced abstract classes and custom enhancements
/// <summary> ///Abstract Enhanced Classes/// </summary> Public Abstract classAdviceabstract { Public AbstractIMessage Invoke (MarshalByRefObject target, IMethodCallMessage callmessage); } Public classMyadvice:adviceabstract { Public OverrideIMessage Invoke (MarshalByRefObject target, IMethodCallMessage callmessage) { This. Beforeinvoke (target); IMessage message=Delayproxyutil.invokebeproxy (target, callmessage); This. Afterinvoke (target); returnmessage; } protected Virtual voidBeforeinvoke (MarshalByRefObject target) {Console.WriteLine ("before"); } protected Virtual voidAfterinvoke (MarshalByRefObject target) {Console.WriteLine (" After"); } }
Advice
With the above two components, and then the proxy class Delayproxy<t>, the enhanced weaving, simple AOP is already the original prototype.
/// <summary> ///supports generic, deferred-initialization proxy classes, which provide proxies for MarshalByRefObject sub-types/// <para>During the execution of the agent, obtain the enhancements specified by the Adviceattribute, and weave in the enhanced</para> /// </summary> Public classDelayproxy<t>: RealProxywhereT:marshalbyrefobject {Private Static ObjectObjlock =New Object(); /// <summary> ///the object being proxied/// </summary> PrivateT Target; /// <summary> ///whether to defer initialization/// <para>True: Delay, False: no delay</para> /// </summary> Private ReadOnly BOOLdelay; PublicDelayproxy (T Target,BOOLdelay):Base(typeof(T)) { This. target =Target; This. Delay =delay; } /// <summary> ///calling the Proxied object/// <para>support for out ref parameters</para> /// </summary> /// <param name= "msg" ></param> /// <returns></returns> Public OverrideIMessage Invoke (IMessage msg) {if( This. Delay && This. target = =NULL) { Lock(objlock) {if( This. Delay && This. target = =NULL) {T instance= Activator.CreateInstance (typeof(T)) asT; //Automatic Assembly Properties//enable proxy for the Property object and defer initialization of the Proxied object//Delayproxyutil.autowiredproperties (instance); This. target =instance; }}} IMethodCallMessage Callmessage=(IMethodCallMessage) msg; Adviceattribute Attri= reflectionutil.getcustomattribute<adviceattribute>(callmessage.methodbase); if(Attri! =NULL&& Attri. Advice! =NULL) { returnAttri. Advice.invoke ( This. Target, Callmessage); } returnDelayproxyutil.invokebeproxy ( This. Target, Callmessage); } }
Delayproxy
Attached source (MVC4 project without Packages folder): Http://files.cnblogs.com/files/08shiyan/AOPDemo.zip
The source also implements deferred initialization of the Proxied object.
Not to be continued ...
Implement simple AOP Yourself (ii) introduce attribute to specify the enhanced object for the method