前言:直接开干。
使用Autofac进行服务注册实践:
新建三个项目,分别是webapi项目 Wesky.Core.Autofac以及两个类库项目 Wesky.Core.Interface和Wesky.Core.Service。
在Webapi项目下,引用Autofac的三个包:Autofac、Autofac.Configuration和Autofac.Extensions.DependencyInjection 。
在类库下,Interface用于编写Interface接口类;Service用于开发对应的接口实现类。现在先准备了6个接口和实现,用来测试,方法实现都一样,都是打印当前方法名称。如图:
在webapi项目下的Program类里面,添加对autofac工厂(AutofacServiceProviderFactory)的服务实现。如图,需要先 using Autofac.Extensions.DependencyInjection;
在Startup类下面,新建无返回值的方法ConfigureContainer,并且带有一个ContainerBuilder类型的参数。然后在里面添加两个服务的注册,例如ServiceA和ServiceD,用来测试使用:
新增一个控制器TestController,并且实现一个叫Test方法的webapi,用来实验是否依赖注入服务生效:
运行程序,并调用webapi,验证依赖注入的结果:
Autofac依赖注入的几个相对常见的生命周期:
1、瞬时 InstancePerDependency:每次获取的服务实例都不一样;
2、单例 SingleInstance:在整个容器中获取的服务实例都是同一个;
3、作用域 InstancePerLifetimeScope:相同作用域下获取到的服务实例相同;
4、作用域 InstancePerMatchingLifetimeScope(“作用域名称”):可以指定到某一个具体作用域;
5、每次请求 InstancePerRequest:不同的请求获取的服务实例不一样;
6、隐式关系类型的嵌套作用域 InstancePerOwned:可以使用每一个拥有实例的注册来依赖关系限定到拥有的实例。
对应注册的方式如下代码所示:
现在对这些实例的生命周期做个测试,编写一些测试代码,用来验证生命周期:
在方法最后加个断点,然后运行程序。
A1和 A2是瞬时周期进行注册,每次都会产生不同的实例,所以两个实例不一样;
B1 和 B2是单例进行注册,会引用同一个实例,所以两者的实例相等;
C1和C2、C3和C4分别在两个作用域下进行作用域注册,所以在同一个作用域下,C1和C2、C3和C4的实例分别相等;但是C1和C3不属于同一个作用域,所以不相等。D1/2/3/4类似,不再描述。
详情,如图所示:
Autofac通过模块化进行注册服务
新建一个继承自Autofac.Module的类WeskyModule,并在里面提供Load方法的实现(在方法里面进行服务注册),下面使用一些其他方式进行注册,如代码以及注释部分:
在Startup类的ConfigureContainer方法下,注释之前的注册服务,改为引用Module模块来进行服务注册:
运行程序,在注册ServiceE的时候会提示错误,这是因为上面注册时候,排除了ServiceE所导致的,会提示服务没注册,如图:
现在先屏蔽掉对E服务的依赖,查看注册效果,直接在注册以后,访问注册服务的Hello方法,并运行查看结果。说明服务注册成功:
Autofac通过配置文件进行服务注册的方式
Autofac也可以通过配置文件进行注册服务,下面做个简单的例子。
新建一个叫做autofac.json的文件,然后在里面写上两个简单的单例注册。注意:新建的json文件需要设置为始终复制,防止生成以后没有存在根目录里面导致的找不到文件的问题。
然后在WeskyModule里面,注释掉先前的注册,使用以下代码进行获取配置文件的注册,并对A、B(B没有在文件里面注册,正常情况下应该是要报错的) 和C进行测试。
运行程序,可以看到由于B并没有在文件里面注册,所以运行到服务B时候,提示未注册服务异常:
由此可见,通过配置文件进行服务注册符合预期,测试完毕。
Autofac实现AOP切面功能
先添加Autofac.Extras.DynamicProxy的包:
新建一个叫做WeskyAOP的类,并且继承自,然后实现里面的Intercept方法,示例如下:
然后为了方便,我直接在下方新建一个IWeskyTest接口和WeskyTest类,并且提供一个Hello方法进行测试。以及对IWeskyTest添加了上面AOP的标记,如下:
返回WeskyModule里面,把先前注册的内容注释掉,然后添加对新增AOP服务的注册,以及新增服务接口的注册,此处注册为一个单例,不过会行不通,不信的可以自己尝试:
在Test控制器里面,添加对IWeskyTest接口服务的依赖注入,并在测试的api里面调用Hello方法进行测试。打印出AOP里面的两句语句,代表AOP实现成功。注意,以上使用单例或者其他的进行注册是不成功的,必须使用 EnableInterfaceInterceptors (需要using Autofac.Extras.DynamicProxy)
另外,把标记写到实现类上也是OK的,例如:
Autofac通过构造函数注入
如前面内容所示,获取实例都是通过构造函数进行。此处通过构造函数获取实例,还有一种通过构造函数传入IServiceProvider进行获取。该方法可以极大减少构造函数传入的实例过多所导致的构造函数参数臃肿。示例直接使用前篇项目做拓展,在控制器的测试api下面,直接使用。有关示例如下图所示:
设置断点,并运行程序查看效果。可见IWeskyTest接口已经被注入进来,并且可以访问到
Autofac通过属性注入方式
在ServiceA实现类里面,添加IServiceB、IServiceC的属性。并且在ServiceA实现类里面,添加一个测试方法 Hey(),在里面对以上两个属性所对应的接口方法进行调用。代码如下:
以及Hey需要加入到抽象类接口IServiceA:
对IServiceA\B\C进行服务注册。其中,提供属性的服务,注册时候必须使用PropertiesAutowired方式,如下面代码所示:
接着改写控制器里面的Test方法进行测试。对应代码以及解释和对应的运行结果如下图所示:
Autofac通过方法注入方式
改写上面ServiceA的类为如下代码。有关代码说明如图:
对用到的IServiceA和B进行服务注册。如图所示,ServiceA里面提供了方法注入,所以需要在注册A服务的时候,使用OnActivated方法。其中,RegisterService是ServiceA服务里面提供的需要当做方法注入的方法,方法里面的IServiceB是需要被方法注入的抽象类(接口)。以下使用了瞬时,也可以使用其他的,没有限制,包括ServiceB服务注册时候,也可以使用非单例模式,不做限制。
运行程序,如果先后打印ServiceA 和 ServiceB,则代表方法注入成功。运行程序结果如下:
Filter过滤器里面实现支持依赖注入
先编写一个过滤器WeskyFilter,继承自 ActionFilterAttribute。并且在里面添加一个属性注入的IServiceC和一个构造函数注入的IServiceD。
然后在OnActionExecuting和OnActionExecuted方法下面实现一个打印的内容,并且分别打印ServiceC实例和ServiceD实例下面的Hello方法。代码如下:
对IServiceC、D进行服务注册,以及注册WeskyFilter过滤器,用以支持依赖注入:
在控制器里面的Test方法上面,添加过滤器标记,并直接运行进行结果验证:
如图所示,打印出过滤器里面的内容,并且成功访问到了ServiceC和D的Hello方法,代表在过滤器里面实现依赖注入也是可以的。
如果觉得有帮助,欢迎转发、在看和留言。
如果对.NET技术感兴趣,或者愿意分享自己的知识,也欢迎扫码加入我的群聊,7天内有效:
最后再次感谢大家观看~谢谢大家。