首页 > 技术文章 > NETCORE - 依赖注入 - Autofac

1285026182YUAN 2020-05-29 09:10 原文

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 

 

 

 

 

 完成!

 

 

 

 


附代码:https://gitee.com/wuxincaicai/NETCORE.git

引用:

 

推荐阅读