<二>使用castle.core 简单实现AOP

一、实现方式

  • 静态代理:代理模式,装饰器模式。
  • 动态代理:利用反射生成动态代理类。
  • 特性:利用.netcore框架自带的特性框架做封装。比如:Filter
  • Emit:  机器自动生成代理类。比如:castle.core
  • 静态编织:在代码编译的时候动态插入代码。

二、Castle.core使用的Emit的方式动态帮助我们生成代理类,不用我们自己去定义一个类来实现代理了。

1、nuget搜索castle.core 并引用

 2、使用Castle.core的CreateClassProxy动态生成代理类来实现AOP

  • 修改MySqlDBHelper 将show修改为虚方法,新增一个方法show1为非虚方法。
  •  public  class MySqlDBHelper: IDBHelper
        {
            public virtual void show()
            {
                Console.WriteLine("I am Mysql");
            }
            public void show1()
            {
                Console.WriteLine("I am Mysql1");
            }
        }
  • 新建一个CastleAOPProxy类来作为Castle.core的操作类
  •   public class CastleAOPProxy
        {
            public static void show()
            {
                ProxyGenerator generator = new ProxyGenerator();
                MyInterceptor interceptor=new MyInterceptor ();
                IDBHelper dbhelper = generator.CreateClassProxy<MySqlDBHelper>(interceptor);
                Console.WriteLine("生成的类型时:{0}", dbhelper.GetType());
                dbhelper.show();
       dbhelper.show1(); } }
  • 再新建一个类实现Castle.core的标准织入类StandardInterceptor的钩子方法
  •  public class MyInterceptor:StandardInterceptor
        {
            /// <summary>
            /// 调用前拦截
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PreProceed(IInvocation invocation)
            {
                Console.WriteLine("调用前拦截,调用方法:" + invocation.Method.Name);
                base.PerformProceed(invocation);
            }
            /// <summary>
            /// 拦截的方法返回时调用
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PreformProceed(IInvocation invocation)
            {
                Console.WriteLine("调用方法返回时拦截,调用方法:" + invocation.Method.Name);
                base.PostProceed(invocation);
            }
            /// <summary>
            /// 调用后拦截
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PostProceed(IInvocation invocation)
            {
                Console.WriteLine("调用后拦截,调用方法:" + invocation.Method.Name);
                base.PreProceed(invocation);
            }
        }
  • 在Program调用一下看看
  • CastleAOPProxy.show();

     看看上面的执行结果,动态生成的代理类叫做MysqlDBHelperProxy了不是MysqlDBHelper,也就是说Castle给我们动态生成了代理类,并把MyInterceptor里面的钩子方法植入了。但是Show1没有运行钩子方法,也就是说ProxyGenerator只会对虚方法启作用。

 3、使用Castle.core的CreateInterfaceProxyWithTargetInterface动态生成代理类来实现AOP

  • 在CastleAOPProxy中新增一个ShowInterface的方法
  •  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("生成的类型时:{0}", dbhelper.GetType());
                dbhelperProxy.show();
                dbhelperProxy.show1();
            }
  •  修改program中的调用方法
  • CastleAOPProxy.ShowInterface();

     从上面结果看,不管是虚方法还是其他方法都可以实现了AOP。以上是两种使用代理动态织入的方式。

4、使用特性+Castle.core的CreateInterfaceProxyWithTargetInterface来实现AOP

  • 添加一个新的interceptor类叫MyAttributeInterceptor,通过对方式是否加了LogAttribute类型进行过滤是否执行植入逻辑
  •  public class MyAttributeInterceptor : StandardInterceptor
        {
            /// <summary>
            /// 调用前拦截
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PerformProceed(IInvocation invocation)
            { 
                base.PerformProceed(invocation);
                if (!IsLog(invocation))
                    return;
                Console.WriteLine("调用时拦截,调用方法:" + invocation.Method.Name);          
            }
            /// <summary>
            /// 拦截的方法返回时调用
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PostProceed(IInvocation invocation)
            { 
                base.PostProceed(invocation);
                if (!IsLog(invocation))
                    return;
                Console.WriteLine("调用后拦截,调用方法:" + invocation.Method.Name);          
            }
            /// <summary>
            /// 调用后拦截
            /// </summary>
            /// <param name="invocation"></param>
            protected override void PreProceed(IInvocation invocation)
            {      
                base.PreProceed(invocation);
                if (!IsLog(invocation))
                    return;
                Console.WriteLine("调用前拦截,调用方法:" + invocation.Method.Name);  
            }
    
            private bool IsLog(IInvocation invocation)
            {
                var method = invocation.Method;
                if (method.IsDefined(typeof(LogAttribute), true))
                {
                    return true;
                }
                return false;
            }
        }
  • 添加一个特性LogAttribute 
  •  public class LogAttribute:Attribute
        {
        }
  •  给IDBHelper的某个方法加上Log的特性
  • public interface  IDBHelper
        {
            [Log]
            void  show();
            void show1();
        }
  • 在CastleAOPProxy中新增一个ShowAttibuteInterface的方法
  •   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("生成的类型时:{0}", dbhelper.GetType());
                dbhelperProxy.show();
                dbhelperProxy.show1();
            }
  • 在program中调用该方法 
  • CastleAOPProxy.ShowAttibuteInterface();

     如上图所示,添加了Log特性的Show方法显示了MyAttribute中的钩子方法。而show1没有添加的并没有显示。

posted @ 2022-07-18 06:56  许轩霖  阅读(899)  评论(0编辑  收藏  举报