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 = "" }).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
}
}
}

Autofac三种生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency

InstancePerLifetimeScope:同一个Lifetime生成的对象是同一个实例

SingleInstance:单例模式,每次调用,都会使用同一个实例化的对象;每次都用同一个对象;

InstancePerDependency:默认模式,每次调用,都会重新实例化对象;每次请求都创建一个新的对象

//方式二:在注册类型到容器的时候动态注入拦截器(去掉类型上的特性Attribute)
builder.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).InstancePerLifetimeScope().EnableInterfaceInterceptors();

看下面运行结果图

1、InstancePerLifetimeScope

2、SingleInstance

3、InstancePerDependency

AsImplementedInterfaces()  是以接口方式进行注入,注入这些类的所有的公共接口作为服务(除了释放资源)

builder.RegisterAssemblyTypes  注册程序集中符合条件的类型

 Assembly assembly = Assembly.Load(assemblyName);
//Assembly assembly = this.GetType().GetTypeInfo().Assembly;
builder.RegisterAssemblyTypes(assembly).Where(type => !type.IsInterface && !type.IsSealed && !type.IsAbstract
&& type.Name.EndsWith("BLL", StringComparison.OrdinalIgnoreCase))
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LogInterceptor));

每个RegisterAssemblyTypes()调用将仅应用一组规则 - 如果要注册多个不同组的组件,则需要多次调用RegisterAssemblyTypes()

C#使用Autofac实现控制反转IoC和面向切面编程AOP的更多相关文章

  1. Spring之控制反转——IoC、面向切面编程——AOP

      控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...

  2. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  3. Spring框架使用(控制反转,依赖注入,面向切面AOP)

    参见:http://blog.csdn.net/fei641327936/article/details/52015121 Mybatis: 实现IOC的轻量级的一个Bean的容器 Inversion ...

  4. 程序员笔记|Spring IoC、面向切面编程、事务管理等Spring基本概念详解

    一.Spring IoC 1.1 重要概念 1)控制反转(Inversion of control) 控制反转是一种通过描述(在java中通过xml或者注解)并通过第三方去产生或获取特定对象的方式. ...

  5. Spring框架系列(3) - 深入浅出Spring核心之控制反转(IOC)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点; 本节将在此基础上进一步解读IOC的含义以及IOC的使用方式.@pd ...

  6. ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下

    先简单了解一这个几个 名词的意思. 控制反转(IOC) 依赖注入(DI) 并不是某种技术. 而是一种思想.一种面向对象编程法则 什么是控制反转(IOC)?  什么是依赖注入(DI) 可以点击下面链接 ...

  7. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  8. C#依赖注入控制反转IOC实现详解

    原文:C#依赖注入控制反转IOC实现详解 IOC的基本概念是:不创建对象,但是描述创建它们的方式.在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务.容器负责将这些联系在一起. ...

  9. 控制反转IoC简介

    控制反转IoC简介 在实际的应用开发中,我们需要尽量避免和降低对象间的依赖关系,即降低耦合度.通常的业务对象之间都是互相依赖的,业务对象与业务对象.业务对象与持久层.业务对象与各种资源之间都存在这样或 ...

随机推荐

  1. 面试官问我:平常如何对你的 Java 程序进行调优?

    阅读本文大概需要 10 分钟. 作者:张俊城, 郭理勇, 刘建来源:http://t.cn/AiCTERJz Java 应用性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢.接口超时,服务器负 ...

  2. 图上的并行处理 Parallel Processing of Graphs

    Graph 本次学术前沿讲座由邵斌老师主讲,标题已经揭示了主题:Graph.1.5h的talk,听完自觉意犹未尽.本来以为是一节自己没接触过的图形学的talk,没想到讲的很多内容都跟自己学过的很多东西 ...

  3. [Beta]Scrum Meeting#6

    github 本次会议项目由PM召开,时间为5月11日晚上10点30分 时长15分钟 任务表格 人员 昨日工作 下一步工作 木鬼 撰写博客整理文档 撰写博客整理文档 swoip 改进界面 为适应新功能 ...

  4. linux安装yasm报错

    进入yasm-1.2.0, 输入指令 ./configure //编译yasm make && make install //安装yasm,安装完成即可. 报错信息 make[2]: ...

  5. httpcomponents 发送get post请求

    引入的包为: <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <de ...

  6. mysql时间和本地时间相差13个小时的问题

    首先需要查看mysql的当前时区,用time_zone参数 mysql> show variables like '%time_zone%'; +------------------+----- ...

  7. IfcCircle

    An IfcCircle is a curve consisting of a set of points having equal distance from the center. NOTE  A ...

  8. Invalid prop: custom validator check failed for prop "pagination" <Table> vue.runtime.esm

    错误如图 原因,返回数据中没有包括分布的属性

  9. 拼接Sql语句小心得

    在往数据库插入数据时,需要根据数据和数据库中的列信息进行拼接,在本篇文章中,输出小心得.使用语言为 python. 拼接原始列信息 比如待插入数据库列信息为 deptNo,dName, Locate, ...

  10. Ubuntu16.04安装Supervisor

    安装 sudo apt-get install supervisor 启动,否则会报 unix:///tmp/supervisor.sock no such file service supervis ...