前言
在AOP系列文章的第一篇有提到使用Autofac.Extras.DynamicProxy
的Interceptor来实现AOP架构,本篇文章就来详细说明实作的方法。
Autofac 简介
Autofac是一个Ioc
容器,Ioc为英文Inversion of Control
控制反转的意思,控制反转是物件导向程式设计中的一种设计原则,可以用来减低电脑代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫「依赖寻找」(Dependency Lookup)。通过控制反转,物件在被建立的时候,由一个调控系统内所有物件的外界实体,将其所依赖的物件的参照传递(注入)给它。
以上说明参考维基
安装套件
要套用Autofac的Interceptor,主要需要安装三个套件分别是:
Autofac
Autofac.Extras.DynamicProxy
Castle.Core
Castle.Core
主要功能是用来定义Interceptor的,而Autofac.Extras.DynamicProxy
的功能是来将Interceptor与Autofac绑定在一起,让有在DI Container注册的服务(Service class)可以拥有AOP的功能,所以在实现AOP架构上,三者缺一不可。
设定与使用
从无到有设定拦截器Interceptor,一共会有三个步骤。
设计拦截器绑定拦截器服务Service挂载Interceptor设定之后再来就是看结果,以下就让我慢慢说明,正篇开始啰!
设计拦截器
以例外处理为例,并使用NLog套件记录错误资讯,程式码如下。
/// <summary>/// 例外处理Interceptor/// </summary>public class ExceptionHandleInterceptor : IInterceptor{ /// <summary> /// 例外处理内容 /// </summary> /// <param name="invocation"></param> public void Intercept(IInvocation invocation) { //初始化NLog var logger = LogManager.GetLogger(invocation.GetType().FullName); try { //执行方法 invocation.Proceed(); } catch (Exception ex) { //若有例外发生,进行下列处理 //若回传值类型不为void if (invocation.Method.ReturnType != typeof(void)) { try { //尝试传回初始值 invocation.ReturnValue = Activator.CreateInstance(invocation.Method.ReturnType); } catch { //失败则传回null invocation.ReturnValue = null; } } } }}
绑定拦截器(Interceptor)
首先在专案的AppStart资料夹新增一个AutofacConfig.cs,用来先设定Autofac,注册需要套用Autofac的服务(Service class),这边我会用一层Interface来让Service的Class继承,所以注册的时候是用Interface来注册,程式码如下。
public class AutofacConfig{public static IContainer container;public static void Bootstrap(){var builder = new ContainerBuilder(); //注册服务 TestService //TestService继承于IService介面 //并且允许挂载拦截器builder.RegisterType<TestService>().As<IService>().EnableInterfaceInterceptors(); //注册例外处理Interceptorbuilder.RegisterType(typeof(ExceptionHandleInterceptor));container = builder.Build();}}
接着在专案的Startup.cs,执行AutofacConfig的设定
public partial class Startup{ public void Configuration(IAppBuilder app) { //执行Autofac的设定 AutofacConfig.Bootstrapper(app); }}
服务Service挂载Interceptor
要在服务类别挂载Interceptor,有两种做法,第一种是直接在Service上面加入Intercept标籤,并且标注Interceptor的类型,如下。
做法A:在Service挂载Interceptor标籤
[Intercept(typeof(ExceptionLogInterceptor))]public class TestService : IService{}
第二种作法更全面也更简单一些,只要在刚刚的AutofacConfig绑定就好,就可以不用一个一个Service加上标籤,语法如下。
作法B:在AutofacConfig就绑定Interceptor
//注册Interface并绑定Interceptorbuilder.RegisterType<TestService>() .As<IService>() .EnableInterfaceInterceptors() //以下两行绑定Interceptor .InterceptedBy(typeof(ExceptionHandleInterceptor));
所以在Service上面的Intercept标籤就可以移除。
//这行可以拿掉[Intercept(typeof(ExceptionLogInterceptor))]
产生带有Interceptor的Service物件
绑定结束后,若要使用带有Interceptor的Service,记得不能直接new一个服务类别,要用以下语法,透过Autofac来产生服务类别,Interceptor才有效用。
var service = AutofacConfig.container.Resolve<TService>(); service.Function();
执行Function后结果
在TestService内,加入一个TestFunctionWithException方法,来进行测试,变更后的程式码如下。
方法内容
public class TestService : IService{public int TestFunctionWithException(int x, int y) { //直接抛出错误讯息为 Test Error的例外 throw new Exception("Test Error."); }}
Log纪录内容
2019-11-04 18:20:55.3275 | ERROR | RuntimeMethodInfo | 引动过程的目标传回例外状况。 | System.Reflection.TargetInvocationException: 引动过程的目标传回例外状况。 ---> System.Exception: Test Error. 于 .......
可以看到Test Error已经被自动记录到所设定的Log档案。
自订Interceptor
若是想要自己定义一个Interceptor,则新增类别并继承IInterceptor介面,範本如下,请记得invocation.Proceed()
还是要写上去,让你的Interceptor处理完他的事情后,方法可以继续进行。
public class CustomInterceptor : IInterceptor{public void Intercept(IInvocation invocation){//what you want to do....//↓↓↓↓继续执行↓↓↓↓invocation.Proceed();}}
总结
本篇文章示範了使用Autofac的Interceptor功能来实作AOP,过程其实并不难,这么简单的几个步骤,就可以省去不少重工,所取得的效益十分的高,希望能够帮到各位伙伴们。在这边各位也许会有以下疑问,若不使用Autofac,是否也能实现AOP的框架?
下篇即将介绍,敬请期待。
参考资源
[AOP系列]简单介绍AOP的概念
AOP 观念与术语
Autofac + Interceptors(AOP) 动态代理