1. Ways of implementation
- Static agent: agent mode, decorator mode.
- Dynamic proxy: Generate dynamic proxy classes from reflection.
- Features: Utilization. The netcore framework's own feature framework is encapsulated. For example: Filter
- Emit: Machine automatically generates proxy classes. Examples: castle.core
- Static weaving: Dynamic insertion of code during code compilation.
2. Castle. The Emit approach Core uses dynamically helps us generate proxy classes without having to define a class ourselves to implement the proxy.
1. nuget searches castle.core and reference
2. Use Castle.core's CreaeClassProxy dynamically generates proxy classes to implement AOP
- Modify MySqlDBHelper to change show to a virtual method and add a new method, show1, to be a non-virtual method.
-
public class MySqlDBHelper: IDBHelper { public virtual void show() { Console.WriteLine("I am Mysql"); } public void show1() { Console.WriteLine("I am Mysql1"); } }
- Create a new CastleAOPProxy class as Castle. Operation class of core
-
public class CastleAOPProxy { public static void show() { ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor=new MyInterceptor (); IDBHelper dbhelper = generator.CreateClassProxy<MySqlDBHelper>(interceptor); Console.WriteLine("When generating a type:{0}", dbhelper.GetType()); dbhelper.show();
dbhelper.show1(); } } - Create a new class to implement Castle.core's Standard-woven Standard Interceptor-like hook method
-
public class MyInterceptor:StandardInterceptor { /// <summary> /// Pre-call interception /// </summary> /// <param name="invocation"></param> protected override void PreProceed(IInvocation invocation) { Console.WriteLine("Pre-call interception,Call method:" + invocation.Method.Name); base.PerformProceed(invocation); } /// <summary> /// Called when the intercepted method returns /// </summary> /// <param name="invocation"></param> protected override void PreformProceed(IInvocation invocation) { Console.WriteLine("Intercept when calling method return,Call method:" + invocation.Method.Name); base.PostProceed(invocation); } /// <summary> /// Post-call interception /// </summary> /// <param name="invocation"></param> protected override void PostProceed(IInvocation invocation) { Console.WriteLine("Post-call interception,Call method:" + invocation.Method.Name); base.PreProceed(invocation); } }
- Have a look at the Program call
-
CastleAOPProxy.show();
Looking at the execution above, the dynamically generated proxy class called MysqlDBHelperProxy is not MysqlDBHelper, which means Castle dynamically generated the proxy class for us and implanted the hook method inside MyInterceptor. Show1 does not run the hook method, which means that ProxyGenerator only works on virtual methods.
3. Use Castle.core's CreaeInterfaceProxyWithTargetInterface dynamically generates proxy classes to implement AOP
- A new ShowInterface method in CastleAOPProxy
-
public static void ShowInterface() { ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor = new MyInterceptor(); IDBHelper dbhelper = new MySqlDBHelper(); IDBHelper dbhelperProxy = generator.CreateInterfaceProxyWithTargetInterface<IDBHelper>(dbhelper,interceptor); Console.WriteLine("When generating a type:{0}", dbhelper.GetType()); dbhelperProxy.show(); dbhelperProxy.show1(); }
- Modify the calling method in program
-
CastleAOPProxy.ShowInterface();
From the above results, both virtual and other methods can implement AOP. These are two ways to use proxy dynamic weaving.
4. Use features + Castle.core's CreaeInterfaceProxyWithTargetInterface implements AOP
- Adding a new interceptor class called MyAttributeInterceptor filters whether or not the implant logic is performed by adding a LogAttribute type to the method
-
public class MyAttributeInterceptor : StandardInterceptor { /// <summary> /// Pre-call interception /// </summary> /// <param name="invocation"></param> protected override void PerformProceed(IInvocation invocation) { base.PerformProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("Intercept on Call,Call method:" + invocation.Method.Name); } /// <summary> /// Called when the intercepted method returns /// </summary> /// <param name="invocation"></param> protected override void PostProceed(IInvocation invocation) { base.PostProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("Post-call interception,Call method:" + invocation.Method.Name); } /// <summary> /// Post-call interception /// </summary> /// <param name="invocation"></param> protected override void PreProceed(IInvocation invocation) { base.PreProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("Pre-call interception,Call method:" + invocation.Method.Name); } private bool IsLog(IInvocation invocation) { var method = invocation.Method; if (method.IsDefined(typeof(LogAttribute), true)) { return true; } return false; } }
- Add an attribute LogAttribute
-
public class LogAttribute:Attribute { }
- Add Log to a method of IDBHelper
-
public interface IDBHelper { [Log] void show(); void show1(); }
- A new ShowAttibuteInterface method in CastleAOPProxy
-
public static void ShowAttibuteInterface() { ProxyGenerator generator = new ProxyGenerator(); MyAttributeInterceptor interceptor = new MyAttributeInterceptor(); IDBHelper dbhelper = new MySqlDBHelper(); IDBHelper dbhelperProxy = generator.CreateInterfaceProxyWithTargetInterface<IDBHelper>(dbhelper, interceptor); Console.WriteLine("When generating a type:{0}", dbhelper.GetType()); dbhelperProxy.show(); dbhelperProxy.show1(); }
- Call this method in program
-
CastleAOPProxy.ShowAttibuteInterface();
The Show method with the Log attribute added shows the hook method in MyAttribute, as shown in the figure above. show1 was not added and was not displayed.