NETCORE - 依赖注入 - Autofac
NETCORE - 依赖注入 - Autofac
安装二个 Autofac 的 NuGet包
一. 逐个接口进入注册
项目结构:
新增 ITestService 接口
public interface ITestService { string GetTest(); }
新增 类
public class TestService : ITestService { public string GetTest() { return "a! lalalalalla"; } }
大多时候,我们都是 以下方式进行依赖注入
在startup.cs 中修改 ConfigureServices 方法
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); //初始化容器 var builder = new ContainerBuilder(); //管道寄居 builder.Populate(services); builder.RegisterType<TestService>().As<ITestService>();//TestService注入到ITestService
////注入的生命周期
//builder.RegisterType<Service.TestService>().As<IService.ITestService>();//暂存生存期
//builder.RegisterType<Service.TestService>().As<IService.ITestService>().InstancePerLifetimeScope();//范围生存期
//builder.RegisterType<Service.TestService>().As<IService.ITestService>().SingleInstance();//单例生存期
//构造 var ApplicationContainer = builder.Build(); //将AutoFac反馈到管道中 return new AutofacServiceProvider(ApplicationContainer); }
新增 TestController WebAPI控制器
[Route("api/[controller]")] public class TestController : Controller { private IService.ITestService _testService; public TestController(IService.ITestService testService) { this._testService = testService; } [Route("GetTest")] [HttpGet] public string GetTest() { return this._testService.GetTest(); } }
查看结果,可读取到 GetTest 方法的 返回数据。
随着业务的增长,接口跟实现类会越来越多,还需要手动一个个的注册依赖项,有时候会出现忘了写配置,导致程序报错,如果是多人开发,可能还会导致代码冲突,后期维护起来相对来说比较麻烦。
二. Autofac自动注入
项目结构:
准备一个 NETCORE.Autofac.Respository 类库
新增 接口:IPersonRepository.cs,与实现类:PersonRepository.cs
public interface IPersonRepository { string Eat(); }
public class PersonRepository : IPersonRepository { public string Eat() { return "吃饭"; } }
准备另一个 NETCORE.Autofac.PersonService类库
新增 接口:IPersonService.cs,与实现类:PersonService.cs
public interface IPersonService { string Eat(); }
public class PersonService:IPersonService { private IPersonRepository _personRespository; //通过构造函数注入 repository public PersonService(IPersonRepository personRespository) { _personRespository = personRespository; } public string Eat() { return _personRespository.Eat(); } }
在webapi项目中(NETCORE.Autofac):
将Startup.cs中的ConfigureServices
返回类型改为IServiceProvider,然后新起一个方法RegisterAutofac把创建容器的代码放到其中,然后建一个
AutofacModuleRegister类继承Autofac的Module,然后重写Module的Load方法 来存放新组件的注入代码,避免Startup.cs文件代码过多混乱。
startup.cs 文件
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); return RegisterAutofac(services);//注册Autofac }
在startup.cs 中新增 RegisterAutofac 方法
private IServiceProvider RegisterAutofac(IServiceCollection services) { //实例化Autofac容器 var builder = new ContainerBuilder(); //将Services中的服务填充到Autofac中 builder.Populate(services); //新模块组件注册 builder.RegisterModule<AutofacModuleRegister>(); //创建容器 var Container = builder.Build(); //第三方IOC接管 core内置DI容器 return new AutofacServiceProvider(Container); }
新增 AutofacModuleRegister.cs 类
using Autofac; using Autofac.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using AutofacIn = Autofac;//给引入的Autofac重命名,因为与命名空间 【NETCORE.Autofac】名称重复了 namespace NETCORE.Autofac { public class AutofacModuleRegister : AutofacIn.Module { //重写Autofac管道Load方法,在这里注册注入 protected override void Load(ContainerBuilder builder) { //注册Service中的对象,Service中的类要以Service结尾,否则注册失败 builder.RegisterAssemblyTypes(GetAssemblyByName("NETCORE.Autofac.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces(); //注册Repository中的对象,Repository中的类要以Repository结尾,否则注册失败 builder.RegisterAssemblyTypes(GetAssemblyByName("NETCORE.Autofac.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces(); } /// <summary> /// 根据程序集名称获取程序集 /// </summary> /// <param name="AssemblyName">程序集名称</param> /// <returns></returns> public static Assembly GetAssemblyByName(String AssemblyName) { return Assembly.Load(AssemblyName); } } }
新增 控制器 PersonController
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using NETCORE.Autofac.Service; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace NETCORE.Autofac.Controllers { [Route("api/[controller]")] public class PersonController : Controller { private IPersonService _personService; //通过构造函数注入Service public PersonController(IPersonService personService) { this._personService = personService; } [Route("Eat")] [HttpGet] public JsonResult Eat() { var eatRes = this._personService.Eat(); return new JsonResult(new { eat = eatRes }); } } }
调用 https://localhost:5001/api/person/eat:
三. 一个接口多个实现的情况
在service项目中,
增加接口:IPayService.cs
public interface IPayService { string Pay(); }
增加两个实现类 AliPayService.cs 、WxPayService.cs
public class AliPayService : IPayService { public string Pay() { return "支付宝支付"; } }
public class WxPayService : IPayService { public string Pay() { return "微信支付"; } }
在webapi 项目(NETCORE.Autofac)中,
增加PayController.cs 控制器
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using NETCORE.Autofac.Service; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace NETCORE.Autofac.Controllers { [Route("api/[controller]")] public class PayController : Controller { private IPayService _payService; public PayController(IPayService payService) { _payService = payService; } [Route("GetPayType")] [HttpGet] public JsonResult GetPayType() { string paytype = this._payService.Pay(); return new JsonResult(new { paytype = paytype }); } } }
反问地址 https://localhost:5001/api/pay/getpaytype:
最后得到的是微信支付,因为两个对象实现一个接口的时候,注册时后面注册的会覆盖前面注册的。
如果我想得到支付宝支付要怎么做呢?
我们可以用另外一种注册方式RegisterType,修改注册方式AutofacModuleRegister.cs。
单独注册这个接口。
//重写Autofac管道Load方法,在这里注册注入 protected override void Load(ContainerBuilder builder) { //注册Service中的对象,Service中的类要以Service结尾,否则注册失败 builder.RegisterAssemblyTypes(GetAssemblyByName("NETCORE.Autofac.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces(); //注册Repository中的对象,Repository中的类要以Repository结尾,否则注册失败 builder.RegisterAssemblyTypes(GetAssemblyByName("NETCORE.Autofac.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces(); //单独注册 builder.RegisterType<WxPayService>().Named<IPayService>(typeof(WxPayService).Name); builder.RegisterType<AliPayService>().Named<IPayService>(typeof(AliPayService).Name); }
新增 webapi 控制器(PayEachController ):
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Autofac; using Microsoft.AspNetCore.Mvc; using NETCORE.Autofac.Service; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 namespace NETCORE.Autofac.Controllers { [Route("api/[controller]")] public class PayEachController : Controller { private IPayService _wxPayService; private IPayService _aliPayService; private IComponentContext _componentContext;//Autofac上下文 public PayEachController(IComponentContext componentContext) { _componentContext = componentContext; //解释组件 _wxPayService = _componentContext.ResolveNamed<IPayService>(typeof(WxPayService).Name); _aliPayService = _componentContext.ResolveNamed<IPayService>(typeof(AliPayService).Name); } [Route("GetPayType")] [HttpGet] public JsonResult GetPayType() { string paytype_wx = this._wxPayService.Pay(); string paytype_ali = this._aliPayService.Pay(); return new JsonResult(new { weixinPay = paytype_wx, aliPay = paytype_ali }); } } }
访问地址 https://localhost:5001/api/payEach/getpaytype
完成!
.NET6 中使用
添加nuget包
1. 创建AutoFacManager类
using Autofac; using System.Reflection; namespace RailAssist.Controllers.Middleware { public class AutoFacManager:Autofac.Module { protected override void Load(ContainerBuilder builder) { var IApiServices = Assembly.Load("RailAssist.Service"); var ApiServices = Assembly.Load("RailAssist.Service"); builder.RegisterAssemblyTypes(IApiServices).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces(); builder.RegisterAssemblyTypes(ApiServices).Where(t => t.Name.EndsWith("Services")).AsImplementedInterfaces(); } } }
2. 在program中引入
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer<ContainerBuilder>(builder => { builder.RegisterModule(new AutoFacManager()); });
完成
附代码:https://gitee.com/wuxincaicai/NETCORE.git
引用: