C#使用Autofac实现控制反转IoC和面向切面编程AOP
2023-09-11 14:21:56 时间
C#使用Autofac实现控制反转IoC和面向切面编程AOP
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 { /// <summary> /// 拦截器 需要实现 IInterceptor接口 Intercept方法 /// </summary> public class LogInterceptor : IInterceptor { /// <summary> /// 拦截方法 打印被拦截的方法执行前的名称、参数和方法执行后的 返回结果 /// </summary> /// <param name="invocation">包含被拦截方法的信息</param> 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<IInterceptor>("log-calls"); //类型注入 builder.Register(c => new LogInterceptor()); //或者 builder.RegisterType<LogInterceptor>();
4. 启用拦截器
启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
EnableInterfaceInterceptors方法会动态创建一个接口代理
EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法
注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面两个方法
//启用类代理拦截 //方式一:给类型上加特性Attribute builder.RegisterType<Student>().EnableClassInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) builder.RegisterType<Teacher>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //启用接口代理拦截 //方式一:给类型上加特性Attribute builder.RegisterType<Man>().As<IPerson>().EnableInterfaceInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) builder.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors();
5. 指明要拦截的类型
有两种方法:
第一种:给类型加上特性Attribute
第二种:在注册类型到容器的时候动态注入拦截器
//动态注入拦截器 builder.RegisterType<Student>().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 { /// <summary> /// 继承接口,并实现方法,给类型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Student { public string Name; public Teacher Teacher; public Subject Subject; /// <summary> /// 必须是虚方法 /// </summary> public virtual void Say() { Console.WriteLine("你正在调用Say方法!学生姓名:" + Name); } } [Intercept(typeof(LogInterceptor))] public class Teacher { /// <summary> /// 必须是虚方法 /// </summary> public virtual void Show() { Console.WriteLine("I am Teacher's class !"); } } public class Subject { /// <summary> /// 必须是虚方法 /// </summary> 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<LogInterceptor>(); //方式一:给类型上加特性Attribute builder.RegisterType<Student>().EnableClassInterceptors(); builder.RegisterType<Teacher>().EnableClassInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) //builder.RegisterType<Teacher>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //builder.RegisterType<Student>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //属性注入 builder.Register(c => new Student { Teacher = c.Resolve<Teacher>(), Subject = new Subject(), Name = "张三" }); using (var container = builder.Build()) { //从容器获取对象 var Student = container.Resolve<Student>(); 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 { /// <summary> /// 定义一个接口 /// </summary> 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 { /// <summary> /// 继承接口,并实现方法,给类型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Man: IPerson { public string Age; public void Say(string Name) { Console.WriteLine("男人调用Say方法!姓名:" + Name + ",年龄:" + Age); } } /// <summary> /// 继承接口,并实现方法,给类型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Woman : IPerson { public void Say(string Name) { Console.WriteLine("女人调用Say方法!姓名:" + Name); } } /// <summary> /// 管理类 /// </summary> public class PersonManager { IPerson _Person; /// <summary> /// 根据传入的类型动态创建对象 /// </summary> /// <param name="ds"></param> 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<LogInterceptor>(); //构造函数注入(只要调用者传入实现该接口的对象,就实现了对象创建,下面两种方式) builder2.RegisterType<PersonManager>(); //方式一:给类型上加特性Attribute //属性注入 builder2.Register<Man>(c => new Man { Age = "20" }).As<IPerson>().EnableInterfaceInterceptors(); //builder2.RegisterType<Man>().As<IPerson>().EnableInterfaceInterceptors(); builder2.RegisterType<Woman>().Named<IPerson>("Woman").EnableInterfaceInterceptors(); //方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute) //builder2.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); //builder2.RegisterType<Woman>().Named<IPerson>("Woman").InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); using (var container = builder2.Build()) { //从容器获取对象 var Manager = container.Resolve<PersonManager>(); Manager.Say("管理员"); var Person = container.Resolve<IPerson>(); Person.Say("张三"); var Woman = container.ResolveNamed<IPerson>("Woman"); Woman.Say("王萌"); } Console.ReadLine(); #endregion } } }
分类: .NET AOP
相关文章
- c# 中内部类的简单介绍 C#内部类
- Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解
- 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
- 装饰者模式的学习(c#) EF SaveChanges() 报错(转载) C# 四舍五入 保留两位小数(转载) DataGridView样式生成器使用说明 MSSQL如何将查询结果拼接成字符串 快递查询 C# 通过smtp直接发送邮件 C# 带参访问接口,WebClient方式 C# 发送手机短信 文件 日志 写入 与读取
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
- C#之快速排序 C#之插入排序 C#之选择排序 C#之冒泡排序
- Word控件Spire.Doc 【页眉页脚】教程(10): 锁定标题以防止在 C# 中编辑 word 文档
- Word控件Spire.Doc 【Table】教程(9): 通过在 C# 中克隆来插入现有表
- Word控件Spire.Doc 转换教程(二十六):在 C#、VB.NET 中将 Word 转换为 EPUB 时添加封面图片
- C#学习记录——流程控制:布尔逻辑、布尔按位运算符和赋值运算符、运算符优先级的更新、分支
- C#,数值计算,完整全面的复数(Complex)类的源代码
- [C#] Direct2D 学习笔记 (一)vb.net转换为c#
- C#修改文件或文件夹的权限,为指定用户、用户组添加完全控制权限
- C# lambda表达式
- C# 枚举简析
- C# String.Format的格式限定符与Format方法将多个对象格式化一个字符串原理
- C#常用的form窗体属性(最大化、最小化、窗体居中)
- C#使用Autofac实现控制反转IoC和面向切面编程AOP
- C#-中IO的应用
- C#如何控制方法的执行时间,超时则强制退出方法执行
- c#转义字符
- c#代码规则,C#程序中元素的命名规范