.NET 通过 Autofac 和 DynamicProxy 实现AOP

  什么是AOP?引用百度百科:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。实现AOP主要由两种方式,一种是编译时静态植入,优点是效率高,缺点是缺乏灵活性,.net下postsharp为代表者(这个是收费的)。另一种方式是动态代理,优缺点与前者相反,动态为目标类型创建代理,通过代理调用实现拦截。AOP能做什么,常见的用例是事务处理、日志记录等等。下面就讲讲Autofac怎么实现AOP,Autofac是一个.net下非常优秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP简直是如虎添翼。Autofac的AOP是通过Castle(也是一个容器)项目的核心部分实现的,名为Autofac.Extras.DynamicProxy,顾名思义,其实现方式为动态代理。

  使用前的准备:

    通过Nuget安装程序包 :Autofac、Autofac.Extras.DynamicProxy,安装成功之后会增加三个引用

  下面正式开始了!

  第一步:创建拦截器

  下面是一个简单的拦截器示例,该拦截器的功能是显示被拦截的方法名称、参数列表和返回结果

 1  /// <summary>
 2     /// 拦截器 需要实现 IInterceptor接口 Intercept方法
 3     /// </summary>
 4     public class CallLogger: IInterceptor
 5     {
 6         TextWriter _output;
 7 
 8         public CallLogger(TextWriter output)
 9         {
10             _output = output;
11         }
12 
13         /// <summary>
14         /// 拦截方法 打印被拦截的方法执行前的名称、参数和方法执行后的 返回结果
15         /// </summary>
16         /// <param name="invocation">包含被拦截方法的信息</param>
17         public void Intercept(IInvocation invocation)
18         {
19             
20             _output.WriteLine("你正在调用方法 \"{0}\"  参数是 {1}... ",
21               invocation.Method.Name,
22               string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));
23 
24             //在被拦截的方法执行完毕后 继续执行
25             invocation.Proceed();
26 
27             _output.WriteLine("方法执行完毕,返回结果:{0}", invocation.ReturnValue);
28         }
29     }

  第二步:注册拦截器到Autofac容器

  拦截器必须注册到Aufofac容器中,可以通过拦截器类型或者命名注入,这两种方式会让使用拦截器的方法有所不同(后面会讲到)。

1             // 命名注入
2             builder.Register(c => new CallLogger(Console.Out))
3                    .Named<IInterceptor>("log-calls");
4 
5             // 类型注入
6             builder.Register(c => new CallLogger(Console.Out));    

  第三步:启用拦截器

  启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。

  EnableInterfaceInterceptors方法会动态创建一个接口代理

  EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法

  启用拦截器示例代码:

            //启用类代理拦截
            builder.RegisterType<Circle>().EnableClassInterceptors();
            //启用接口代理拦截
            builder.RegisterType<Circle>().EnableInterfaceInterceptors();

  第四步:指明要拦截的类型

  有两种方法:

    第一种:给类型加上特性Attribute

    第二种:在注册类型到容器的时候动态注入拦截器

1             //动态注入拦截器CallLogger
2             builder.RegisterType<Circle>().InterceptedBy(typeof(CallLogger)).EnableClassInterceptors();

  第五步:测试效果了

    1.类代理拦截

    Circle类代码:

     2.接口代理拦截

     IShape接口代码:

1 public interface IShape
2     {
3         /// <summary>
4         /// 形状的面积
5         /// </summary>
6         void Area();
7 
8     }

    Circle类代码:

1 public class Circle:IShape
2     {
3         //重写父类抽象方法
4         public void Area()
5         {
6             Console.WriteLine("你正在调用圆求面积的方法");
7         }
8     }

    如果有什么地方写得不对欢迎批评改正,如果有什么疑问,欢迎提问。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java学习123

HTTP 头部详细解释

3488
来自专栏娱乐心理测试

SDWebImage源码解读(一)

SDWebImage 是目前最流行、使用最广泛的第三方图片处理框架,它不仅能够异步加载网络图片,还提供了一套图片缓存管理机制(内存缓存+磁盘缓存),功能非常强大...

353
来自专栏大内老A

[WCF REST] 通过ASP.NET Output Caching实现声明式缓存

ASP.NET的输出缓存(Output Caching)机制允许我们针对整个Web页面或者页面的某个部分(主要针对用户控件)最终呈现的HTML进行缓存。对于后续...

1746
来自专栏Create Sun

基础拾遗------redis详解

前言   这篇文章和以往的基础拾遗有所不同,以前的介绍的都是c#基础,今天介绍的是redis。因为项目中一只在使用,我想现在大部分项目中都会用到nosql,缓存...

2855
来自专栏Python

logging模块

logging模块 函数式简单配置 import logging logging.debug('debug message') logging.info...

1897
来自专栏一直在跳坑然后爬坑

Flutter “跳转页面”(二)前言正文

写了这么多文章,有翻译文档的,有自己理解的,也不知道到底是怎么样的风格更能让人接受,希望大家能给点意见或建议。

1032
来自专栏老码农专栏

在ActFramework中进行后台任务调度

952
来自专栏Young Dreamer

Vue Router的懒加载路径

1191
来自专栏JetpropelledSnake

Python学习笔记之解读Socketserver之Tcpserver

1152
来自专栏北京马哥教育

用Python爬下十几万本小说,再也不会闹书荒!

自从看了师傅爬了顶点全站之后,我也手痒痒的,也想爬一个比较牛逼的小说网看看,于是选了宜搜这个网站,好了,马上开干,这次用的是mogodb数据库,感觉mysql太...

3315

扫码关注云+社区