Self-implemented simple AOP (2) Introduce Attribute to specify the enhancement object for the method, aopattribute
Preface: Self-Implementation of simple AOP (I)
In the previous article, I briefly introduced the implementation of AOP. Next, Attribute is introduced to specify the enhancement object for the method to implement a simple AOP.
Note: It specifies the enhancement object, "object", that is, Attribute tag, which is actually an object. With polymorphism, you can easily implement enhanced scaling.
Custom Attribute
/// <Summary> /// mark the specified enhancement object for the method // <para> the specified enhancement, </para> /// </summary> [AttributeUsage (AttributeTargets. method, Inherited = false, AllowMultiple = false)] public sealed class AdviceAttribute: attribute {// <summary> // enhancement object // </summary> public AdviceAbstract Advice {get; private set ;} /// <summary> /// use the default enhancement object of the specified type /// <para> If the type is null, no enhancement is used </para> /// </para>/ summary> // <param name = "type"> </param> public AdviceAttribute (Type type): this (type, string. empty) {}/// <summary> /// use the public static method name to initialize the enhancement object of the specified type. /// <para> If the type is null, no enhancement is 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> public AdviceAttribute (Type type, string methodName) {// if the type is null, no enhancement if (type = null) {this. advice = null; return;} if (string. isNullOrWhiteSpace (methodName) {this. advice = Activator. createInstance (type) as AdviceAbstract; return;} this. advice = type. invokeMember (methodName, System. reflection. bindingFlags. invokeMethod | System. reflection. bindingFlags. public | System. reflection. bindingFlags. static, null) as AdviceAbstract;} # region the following two methods do not work very well and are not recommended, therefore, the constructor is private. // <summary> // use the parameter list to initialize the object of the specified type. // </summary> /// <param name = "type"> type </param> /// <param name = "objs"> parameter list </param> private AdviceAttribute (type Type, params object [] objs) {this. advice = Activator. createInstance (type, objs) as AdviceAbstract ;} /// <summary> /// use the name parameter to initialize the enhancement object of the specified type. // </summary> /// <param name = "namedParameter"> // the name parameter list of the form parameters separated by colons and semicolons // <para> supports the following data types: string, int, bool and types that can be deserialized by static Parse </para> /// </param> /// <param name = "type"> </param> private AdviceAttribute (string namedParameter, type type) {this. advice = ReflectionUtil. invokeConstructor (type, namedParameter) as AdviceAbstract;} # endregion}Attribute
Enhanced abstract classes and custom enhancements
/// <Summary> // abstract enhancement class /// </summary> public abstract class AdviceAbstract {public abstract IMessage Invoke (externalbyrefobject target, IMethodCallMessage callMessage );} public class MyAdvice: AdviceAbstract {public override IMessage Invoke (financialbyrefobject target, IMethodCallMessage callMessage) {this. beforeInvoke (target); IMessage message = DelayProxyUtil. invokeBeProxy (target, callMessage); this. afterInvoke (target); return message;} protected virtual void BeforeInvoke (financialbyrefobject target) {Console. writeLine ("Before");} protected virtual void AfterInvoke (financialbyrefobject target) {Console. writeLine ("After ");}}Advice
With the above two components, and with the aid of the proxy class DelayProxy <T>, the enhanced weaving will be achieved, and the simple AOP has become a prototype.
/// <Summary> /// proxy class that supports generics and delayed initialization. It can be used as a proxy for subtypes of externalbyrefobject. /// <para> During proxy execution, obtain the enhancement specified by AdviceAttribute and weave the enhancement </para> /// </summary> public class DelayProxy <T>: RealProxy where T: export albyrefobject {private static object objLock = new object (); // <summary> // the object to be proxy /// </summary> private T target; /// <summary> /// whether to delay initialization /// <para> True: delay, False: no delay </para> /// </summary> private Readonly bool delay; public DelayProxy (T target, bool delay): base (typeof (T) {this.tar get = target; this. delay = delay ;} /// <summary> /// call the proxy object /// <para> supports the out ref parameter </para> /// </summary> /// <param name = "msg"> </param> // <returns> </returns> public override IMessage Invoke (IMessage msg) {if (this. delay & this.tar get = null) {lock (objLock) {if (this. delay & this.tar get = null ){ T instance = Activator. createInstance (typeof (T) as T; // automatically assemble attributes // enable proxy for Attribute objects and delay the initialization of objects to be proxies // DelayProxyUtil. autowiredProperties (instance); this.tar get = instance ;}} IMethodCallMessage callMessage = (IMethodCallMessage) msg; AdviceAttribute attri = ReflectionUtil. getCustomAttribute <AdviceAttribute> (callMessage. methodBase); if (attri! = Null & attri. Advice! = Null) {return attri.Advice.Invoke(this.tar get, callMessage);} return DelayProxyUtil.InvokeBeProxy(this.tar get, callMessage );}}DelayProxy
Source code (MVC4 project does not have packages folder): http://files.cnblogs.com/files/08shiyan/AOPDemo.zip
The source code also implements delayed initialization of the proxy object.
To be continued...