一、为什么使用Autofac?
Autofac是.NET领域最为流行的IoC框架之一,传说是速度最快的一个。
1.1、性能
有人专门做了测试:
1.2、优点
1)与C#语言联系很紧密。C#里的很多编程方式都可以为Autofac使用,例如可以使用Lambda表达式注册组件。
2)较低的学习曲线。学习它非常的简单,只要你理解了IoC和DI的概念以及在何时需要使用它们。
3)支持JSON/XML配置。
4)自动装配。
5)与Asp.Net MVC集成。
6)微软的Orchad开源程序使用的就是Autofac,可以看出它的方便和强大。
1.3、资源
官方网站:http://autofac.org/
GitHub网址:https://github.com/autofac/Autofac
学习资料:Autofac中文文档
二、数据准备
2.1、新建项目
IService下的接口类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkTo.Test.Autofac.IService
{
/// <summary>
/// 动物吠声接口类
/// </summary>
public interface IAnimalBark
{
/// <summary>
/// 吠叫
/// </summary>
void Bark();
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkTo.Test.Autofac.IService
{
/// <summary>
/// 动物睡眠接口类
/// </summary>
public interface IAnimalSleep
{
/// <summary>
/// 睡眠
/// </summary>
void Sleep();
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkTo.Test.Autofac.IService
{
/// <summary>
/// 学校接口类
/// </summary>
public interface ISchool
{
/// <summary>
/// 放学
/// </summary>
void LeaveSchool();
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinkTo.Test.Autofac.IService
{
/// <summary>
/// 学生接口类
/// </summary>
public interface IStudent
{
/// <summary>
/// 增加学生
/// </summary>
/// <param name="studentID">学生ID</param>
/// <param name="studentName">学生姓名</param>
void Add(string studentID, string studentName);
}
}
Service下的接口实现类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinkTo.Test.Autofac.IService;
namespace LinkTo.Test.Autofac.Service
{
/// <summary>
/// 猫类
/// </summary>
public class Cat : IAnimalSleep
{
/// <summary>
/// 睡眠
/// </summary>
public void Sleep()
{
Console.WriteLine("小猫咪睡着了zZ");
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinkTo.Test.Autofac.IService;
namespace LinkTo.Test.Autofac.Service
{
/// <summary>
/// 狗类
/// </summary>
public class Dog : IAnimalBark, IAnimalSleep
{
/// <summary>
/// 吠叫
/// </summary>
public void Bark()
{
Console.WriteLine("汪汪汪");
}
/// <summary>
/// 睡眠
/// </summary>
public void Sleep()
{
Console.WriteLine("小狗狗睡着了zZ");
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinkTo.Test.Autofac.IService;
namespace LinkTo.Test.Autofac.Service
{
/// <summary>
/// 学校类
/// </summary>
public class School : ISchool
{
/// <summary>
/// IAnimalBark属性
/// </summary>
public IAnimalBark AnimalBark { get; set; }
/// <summary>
/// 放学
/// </summary>
public void LeaveSchool()
{
AnimalBark.Bark();
Console.WriteLine("你家的熊孩子放学了⊙o⊙");
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinkTo.Test.Autofac.IService;
namespace LinkTo.Test.Autofac.Service
{
/// <summary>
/// 学生类
/// </summary>
public class Student : IStudent
{
/// <summary>
/// 无参构造函数
/// </summary>
public Student()
{ }
/// <summary>
/// 有参构造函数
/// </summary>
/// <param name="studentID">学生ID</param>
/// <param name="studentName">学生姓名</param>
public Student(string studentID, string studentName)
{
Add(studentID, studentName);
}
/// <summary>
/// 增加学生
/// </summary>
/// <param name="studentID">学生ID</param>
/// <param name="studentName">学生姓名</param>
public void Add(string studentID, string studentName)
{
Console.WriteLine($"新增的学生是:{studentName}");
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using LinkTo.Test.Autofac.IService;
namespace LinkTo.Test.Autofac.Service
{
/// <summary>
/// 动物摇尾巴
/// </summary>
public class AnimalWagging
{
/// <summary>
/// IAnimalBark属性
/// </summary>
IAnimalBark animalBark;
/// <summary>
/// 有参构造函数
/// </summary>
/// <param name="bark">IAnimalBark变量</param>
public AnimalWagging(IAnimalBark bark)
{
animalBark = bark;
}
/// <summary>
/// 摇尾巴
/// </summary>
public virtual void Wagging()
{
animalBark.Bark();
Console.WriteLine("摇尾巴");
}
/// <summary>
/// 计数
/// </summary>
/// <returns></returns>
public static int Count()
{
return 6;
}
/// <summary>
/// 任务
/// </summary>
/// <param name="name">动物名称</param>
/// <returns></returns>
public virtual async Task<string> WaggingAsync(string name)
{
var result = await Task.Run(() => Count());
return $"{name}摇了{result}下尾巴";
}
}
}
2.2、Autofac安装
Client项目右键->管理 NuGet 程序包->Autofac。
三、IoC-注册
3.1、类型注册
a)类型注册:使用RegisterType进行注册。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//注册Autofac组件
ContainerBuilder builder = new ContainerBuilder();
//注册实现类Student,当我们请求IStudent接口的时候,返回的是类Student的对象。
builder.RegisterType<Student>().As<IStudent>();
//上面这句也可改成下面这句,这样请求Student实现了的任何接口的时候,都会返回Student对象。
//builder.RegisterType<Student>().AsImplementedInterfaces();
IContainer container = builder.Build();
//请求IStudent接口
IStudent student = container.Resolve<IStudent>();
student.Add("1001", "Hello");
b)类型注册(别名):假如一个接口有多个实现类,可以在注册时起别名。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dog>().Named<IAnimalSleep>("Dog");
builder.RegisterType<Cat>().Named<IAnimalSleep>("Cat");
IContainer container = builder.Build();
var dog = container.ResolveNamed<IAnimalSleep>("Dog");
dog.Sleep();
var cat = container.ResolveNamed<IAnimalSleep>("Cat");
cat.Sleep();
c)类型注册(枚举):假如一个接口有多个实现类,也可以使用枚举的方式注册。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public enum AnimalType
{
Dog,
Cat
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dog>().Keyed<IAnimalSleep>(AnimalType.Dog);
builder.RegisterType<Cat>().Keyed<IAnimalSleep>(AnimalType.Cat);
IContainer container = builder.Build();
var dog = container.ResolveKeyed<IAnimalSleep>(AnimalType.Dog);
dog.Sleep();
var cat = container.ResolveKeyed<IAnimalSleep>(AnimalType.Cat);
cat.Sleep();
3.2、实例注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterInstance<IStudent>(new Student());
IContainer container = builder.Build();
IStudent student = container.Resolve<IStudent>();
student.Add("1001", "Hello");
3.3、Lambda注册
a)Lambda注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.Register(c => new Student()).As<IStudent>();
IContainer container = builder.Build();
IStudent student = container.Resolve<IStudent>();
student.Add("1001", "Hello");
b)Lambda注册(NamedParameter)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.Register<IAnimalSleep>((c, p) =>
{
var type = p.Named<string>("type");
if (type == "Dog")
{
return new Dog();
}
else
{
return new Cat();
}
}).As<IAnimalSleep>();
IContainer container = builder.Build();
var dog = container.Resolve<IAnimalSleep>(new NamedParameter("type", "Dog"));
dog.Sleep();
3.4、程序集注册
如果有很多接口及实现类,假如觉得这种一一注册很麻烦的话,可以一次性全部注册,当然也可以加筛选条件。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces(); //常用
//builder.RegisterAssemblyTypes(assembly).Where(t=>t.Name.StartsWith("S")).AsImplementedInterfaces(); //带筛选
//builder.RegisterAssemblyTypes(assembly).Except<School>().AsImplementedInterfaces(); //带筛选
IContainer container = builder.Build();
//单实现类的用法
IStudent student = container.Resolve<IStudent>();
student.Add("1001", "Hello");
//多实现类的用法
IEnumerable<IAnimalSleep> animals = container.Resolve<IEnumerable<IAnimalSleep>>();
foreach (var item in animals)
{
item.Sleep();
}
3.5、泛型注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>));
IContainer container = builder.Build();
IList<string> list = container.Resolve<IList<string>>();
3.6、默认注册
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
//对于同一个接口,后面注册的实现会覆盖之前的实现。
//如果不想覆盖的话,可以用PreserveExistingDefaults,这样会保留原来注册的实现。
builder.RegisterType<Dog>().As<IAnimalSleep>();
builder.RegisterType<Cat>().As<IAnimalSleep>().PreserveExistingDefaults(); //指定为非默认值
IContainer container = builder.Build();
var dog = container.Resolve<IAnimalSleep>();
dog.Sleep();
四、IoC-注入
4.1、构造函数注入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<AnimalWagging>();
builder.RegisterType<Dog>().As<IAnimalBark>();
IContainer container = builder.Build();
AnimalWagging animal = container.Resolve<AnimalWagging>();
animal.Wagging();
4.2、属性注入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired(); //常用
IContainer container = builder.Build();
ISchool school = container.Resolve<ISchool>();
school.LeaveSchool();
五、IoC-事件
Autofac在组件生命周期的不同阶段,共对应了5个事件,执行顺序如下所示:
1.OnRegistered->2.OnPreparing->3.OnActivating->4.OnActivated->5.OnRelease
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Student>().As<IStudent>()
.OnRegistered(e => Console.WriteLine("OnRegistered:在注册的时候调用"))
.OnPreparing(e => Console.WriteLine("OnPreparing:在准备创建的时候调用"))
.OnActivating(e => Console.WriteLine("OnActivating:在创建之前调用"))
//.OnActivating(e => e.ReplaceInstance(new Student("1000", "Test")))
.OnActivated(e => Console.WriteLine("OnActivated:在创建之后调用"))
.OnRelease(e => Console.WriteLine("OnRelease:在释放占用的资源之前调用"));
using (IContainer container = builder.Build())
{
IStudent student = container.Resolve<IStudent>();
student.Add("1001", "Hello");
}
六、IoC-生命周期
6.1、Per Dependency
Per Dependency:为默认的生命周期,也被称为"transient"或"factory",其实就是每次请求都创建一个新的对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency(); //常用
IContainer container = builder.Build();
ISchool school1 = container.Resolve<ISchool>();
ISchool school2 = container.Resolve<ISchool>();
Console.WriteLine(school1.Equals(school2));
6.2、Single Instance
Single Instance:就是每次都用同一个对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //实现类所在的程序集名称
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().SingleInstance(); //常用
IContainer container = builder.Build();
ISchool school1 = container.Resolve<ISchool>();
ISchool school2 = container.Resolve<ISchool>();
Console.WriteLine(ReferenceEquals(school1, school2));
6.3、Per Lifetime Scope
Per Lifetime Scope:同一个Lifetime生成的对象是同一个实例。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<School>().As<ISchool>().InstancePerLifetimeScope();
IContainer container = builder.Build();
ISchool school1 = container.Resolve<ISchool>();
ISchool school2 = container.Resolve<ISchool>();
Console.WriteLine(school1.Equals(school2));
using (ILifetimeScope lifetime = container.BeginLifetimeScope())
{
ISchool school3 = lifetime.Resolve<ISchool>();
ISchool school4 = lifetime.Resolve<ISchool>();
Console.WriteLine(school3.Equals(school4));
Console.WriteLine(school2.Equals(school3));
}
七、IoC-通过配置文件使用Autofac
7.1、组件安装
Client项目右键->管理 NuGet 程序包->Autofac.Configuration及Microsoft.Extensions.Configuration.Xml。
7.2、配置文件
新建一个AutofacConfigIoC.xml文件,并将复制到输出目录属性改为始终复制。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
<?xml version="1.0" encoding="utf-8" ?>
<autofac defaultAssembly="LinkTo.Test.Autofac.IService">
<!--无注入-->
<components name="1001">
<type>LinkTo.Test.Autofac.Service.Student, LinkTo.Test.Autofac.Service</type>
<services name="0" type="LinkTo.Test.Autofac.IService.IStudent" />
<injectProperties>true</injectProperties>
</components>
<components name="1002">
<type>LinkTo.Test.Autofac.Service.Dog, LinkTo.Test.Autofac.Service</type>
<services name="0" type="LinkTo.Test.Autofac.IService.IAnimalBark" />
<injectProperties>true</injectProperties>
</components>
<!--构造函数注入-->
<components name="2001">
<type>LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service</type>
<services name="0" type="LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service" />
<injectProperties>true</injectProperties>
</components>
<!--属性注入-->
<components name="3001">
<type>LinkTo.Test.Autofac.Service.School, LinkTo.Test.Autofac.Service</type>
<services name="0" type="LinkTo.Test.Autofac.IService.ISchool" />
<injectProperties>true</injectProperties>
</components>
</autofac>
7.3、测试代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
//加载配置
ContainerBuilder builder = new ContainerBuilder();
var config = new ConfigurationBuilder();
config.AddXmlFile("AutofacConfigIoC.xml");
var module = new ConfigurationModule(config.Build());
builder.RegisterModule(module);
IContainer container = builder.Build();
//无注入测试
IStudent student = container.Resolve<IStudent>();
student.Add("1002", "World");
//构造函数注入测试
AnimalWagging animal = container.Resolve<AnimalWagging>();
animal.Wagging();
//属性注入测试
ISchool school = container.Resolve<ISchool>();
school.LeaveSchool();
八、AOP
8.1、组件安装
Client项目右键->管理 NuGet 程序包->Autofac.Extras.DynamicProxy。
8.2、拉截器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Castle.DynamicProxy;
namespace LinkTo.Test.Autofac.Client
{
/// <summary>
/// 拦截器:需实现IInterceptor接口。
/// </summary>
public class CallLogger : IInterceptor
{
private readonly TextWriter _output;
public CallLogger(TextWriter output)
{
_output = output;
}
/// <summary>
/// 拦截方法:打印被拦截的方法--执行前的名称、参数以及执行后的返回结果。
/// </summary>
/// <param name="invocation">被拦截方法的信息</param>
public void Intercept(IInvocation invocation)
{
//空白行
_output.WriteLine();
//在下一个拦截器或目标方法处理之前的处理
_output.WriteLine($"调用方法:{invocation.Method.Name}");
if (invocation.Arguments.Length > 0)
{
_output.WriteLine($"参数:{string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())}");
}
//调用下一个拦截器(若存在),直到最终的目标方法(Target Method)。
invocation.Proceed();
//获取被代理方法的返回类型
var returnType = invocation.Method.ReturnType;
//异步方法
if (IsAsyncMethod(invocation.Method))
{
//Task:返回值是固定类型
if (returnType != null && returnType == typeof(Task))
{
//定义一个异步方法来等待目标方法返回的Task
async Task Continuation() => await (Task)invocation.ReturnValue;
//Continuation()中并没有使用await,所以Continuation()就如同步方法一样是阻塞的。
invocation.ReturnValue = Continuation();
}
//Task<T>:返回值是泛型类型
else
{
//获取被代理方法的返回类型
var returnTypeT = invocation.Method.ReflectedType;
if (returnTypeT != null)
{
//获取泛型参数集合,集合中的第一个元素等价于typeof(Class)。
var resultType = invocation.Method.ReturnType.GetGenericArguments()[0];
//利用反射获得等待返回值的异步方法
MethodInfo methodInfo = typeof(CallLogger).GetMethod("HandleAsync", BindingFlags.Public | BindingFlags.Instance);
//调用methodInfo类的MakeGenericMethod()方法,用获得的类型T(<resultType>)来重新构造HandleAsync()方法。
var mi = methodInfo.MakeGenericMethod(resultType);
//Invoke:使用指定参数调用由当前实例表示的方法或构造函数。
invocation.ReturnValue = mi.Invoke(this, new[] { invocation.ReturnValue });
}
}
var type = invocation.Method.ReturnType;
var resultProperty = type.GetProperty("Result");
if (resultProperty != null)
_output.WriteLine($"方法结果:{resultProperty.GetValue(invocation.ReturnValue)}");
}
//同步方法
else
{
if (returnType != null && returnType != typeof(void))
_output.WriteLine($"方法结果:{invocation.ReturnValue}");
}
}
/// <summary>
/// 判断是否异步方法
/// </summary>
public static bool IsAsyncMethod(MethodInfo method)
{
return
(
method.ReturnType == typeof(Task) ||
(method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
);
}
/// <summary>
/// 构造等待返回值的异步方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="task"></param>
/// <returns></returns>
public async Task<T> HandleAsync<T>(Task<T> task)
{
var t = await task;
return t;
}
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Castle.DynamicProxy;
namespace LinkTo.Test.Autofac.Client
{
public class CallTester: IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("啥也不干");
invocation.Proceed();
Console.WriteLine("也不干啥");
}
}
}
8.3、测试代码
注意:对于以类方式的注入,Autofac Interceptor要求类的方法必须为virtual方法。如AnimalWagging类的Wagging()、WaggingAsync(string name)都加了virtual修饰符。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
ContainerBuilder builder = new ContainerBuilder();
//注册拦截器
builder.Register(c => new CallLogger(Console.Out));
builder.Register(c => new CallTester());
//动态注入拦截器
//这里定义了两个拦截器,注意它们的顺序。
builder.RegisterType<Student>().As<IStudent>().InterceptedBy(typeof(CallLogger), typeof(CallTester)).EnableInterfaceInterceptors();
//这里定义了一个拦截器
builder.RegisterType<AnimalWagging>().InterceptedBy(typeof(CallLogger)).EnableClassInterceptors();
builder.RegisterType<Dog>().As<IAnimalBark>();
IContainer container = builder.Build();
IStudent student = container.Resolve<IStudent>();
student.Add("1003", "Kobe");
AnimalWagging animal = container.Resolve<AnimalWagging>();
animal.Wagging();
Task<string> task = animal.WaggingAsync("哈士奇");
Console.WriteLine($"{task.Result}");
IoC参考自:
https://www.xin3721.com/ArticlecSharp/c14013.html
https://www.cnblogs.com/GoogleGetZ/p/10218721.html
http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/
https://www.cnblogs.com/kissdodog/p/3611799.html
AOP参考自:
https://www.cnblogs.com/stulzq/p/6880394.html
https://blog.csdn.net/weixin_38211198/article/details/105925821
https://blog.csdn.net/q932104843/article/details/97611912
来源:oschina
链接:https://my.oschina.net/u/4364439/blog/4272243