Autofac是一个.net下非常优秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP简直是如虎添翼。Autofac的AOP是通过Castle(也是一个容器)项目的核心部分实现的,名为Autofac.Extras.DynamicProxy,顾名思义,其实现方式为动态代理。
使用方式比较简单,先新建一个控制台项目,然后在Nuget上搜索Autofac.Aop并安装,如下顺序:
或者通过命令安装:
Install-Package Autofac.Aop
安装成功之后会项目会增加几个个引用,如下图:
1. 创建拦截器
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //先在Nuget上搜索Autofac.Aop安装 using Castle.DynamicProxy; namespace AutofacDEMO { ////// 拦截器 需要实现 IInterceptor接口 Intercept方法 /// public class LogInterceptor : IInterceptor { /// /// 拦截方法 打印被拦截的方法执行前的名称、参数和方法执行后的 返回结果 /// /// 包含被拦截方法的信息 public void Intercept(IInvocation invocation) { Console.WriteLine("方法执行前:拦截{0}类下的方法{1}的参数是{2}", invocation.InvocationTarget.GetType(), invocation.Method.Name, string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())); //在被拦截的方法执行完毕后 继续执行 invocation.Proceed(); Console.WriteLine("方法执行完毕,返回结果:{0}", invocation.ReturnValue); Console.WriteLine(); } } }
2. 创建拦截容器
var builder = new ContainerBuilder();
3. 注册拦截器到Autofac容器
拦截器必须注册到Aufofac容器中,可以通过拦截器类型或者命名注入,这两种方式会让使用拦截器的方法有所不同
// 命名注入 builder.Register(c => new LogInterceptor()).Named("log-calls"); //类型注入 builder.Register(c => new LogInterceptor());
//或者 builder.RegisterType();
4. 启用拦截器
启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
EnableInterfaceInterceptors方法会动态创建一个接口代理
EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法
注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面两个方法
//启用类代理拦截 //方式一:给类型上加特性Attribute builder.RegisterType().EnableClassInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) builder.RegisterType ().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //启用接口代理拦截 //方式一:给类型上加特性Attribute builder.RegisterType ().As ().EnableInterfaceInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) builder.RegisterType ().As ().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors();
5. 指明要拦截的类型
有两种方法:
第一种:给类型加上特性Attribute
第二种:在注册类型到容器的时候动态注入拦截器
//动态注入拦截器 builder.RegisterType().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors();
6. 测试效果如下
第一种:类代理拦截
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { ////// 继承接口,并实现方法,给类型加上特性Attribute /// [Intercept(typeof(LogInterceptor))] public class Student { public string Name; public Teacher Teacher; public Subject Subject; /// /// 必须是虚方法 /// public virtual void Say() { Console.WriteLine("你正在调用Say方法!学生姓名:" + Name); } } [Intercept(typeof(LogInterceptor))] public class Teacher { /// /// 必须是虚方法 /// public virtual void Show() { Console.WriteLine("I am Teacher's class !"); } } public class Subject { /// /// 必须是虚方法 /// public virtual void Show() { Console.WriteLine("I am Subject's class !" ); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { class Program { static void Main(string[] args) { //启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors() //EnableInterfaceInterceptors方法会动态创建一个接口代理 //EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法 //注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面两个方法 #region 启用类代理拦截 //创建拦截容器 var builder = new ContainerBuilder(); //注册拦截器到容器 builder.RegisterType(); //方式一:给类型上加特性Attribute builder.RegisterType ().EnableClassInterceptors(); builder.RegisterType ().EnableClassInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) //builder.RegisterType ().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //builder.RegisterType().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //属性注入 builder.Register(c => new Student { Teacher = c.Resolve(), Subject = new Subject(), Name = "张三" }); using (var container = builder.Build()) { //从容器获取对象 var Student = container.Resolve (); Student.Say(); Student.Subject.Show(); Student.Teacher.Show(); } Console.ReadLine(); #endregion } } }
第二种:接口代理拦截
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AutofacDEMO { ////// 定义一个接口 /// public interface IPerson { void Say(string Name); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { ////// 继承接口,并实现方法,给类型加上特性Attribute /// [Intercept(typeof(LogInterceptor))] public class Man: IPerson { public string Age; public void Say(string Name) { Console.WriteLine("男人调用Say方法!姓名:" + Name + ",年龄:" + Age); } } /// /// 继承接口,并实现方法,给类型加上特性Attribute /// [Intercept(typeof(LogInterceptor))] public class Woman : IPerson { public void Say(string Name) { Console.WriteLine("女人调用Say方法!姓名:" + Name); } } /// /// 管理类 /// public class PersonManager { IPerson _Person; /// /// 根据传入的类型动态创建对象 /// /// public PersonManager(IPerson Person) { _Person = Person; } public void Say(string Name) { _Person.Say(Name); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { class Program { static void Main(string[] args) { //启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors() //EnableInterfaceInterceptors方法会动态创建一个接口代理 //EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法 //注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面两个方法 #region 启用接口代理拦截(推荐用这种方式) //创建拦截容器 var builder2 = new ContainerBuilder(); //注册拦截器到容器 builder2.RegisterType(); //构造函数注入(只要调用者传入实现该接口的对象,就实现了对象创建,下面两种方式) builder2.RegisterType (); //方式一:给类型上加特性Attribute //属性注入 builder2.Register (c => new Man { Age = "20" }).As ().EnableInterfaceInterceptors(); //builder2.RegisterType ().As builder2.RegisterType().EnableInterfaceInterceptors(); ().Named ("Woman").EnableInterfaceInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) //builder2.RegisterType ().As //builder2.RegisterType().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); ().Named using (var container = builder2.Build()) { //从容器获取对象 var Manager = container.Resolve("Woman").InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); (); Manager.Say("管理员"); var Person = container.Resolve (); Person.Say("张三"); var Woman = container.ResolveNamed ("Woman"); Woman.Say("王萌"); } Console.ReadLine(); #endregion } } }