.Net5 WebApi中使用Autofac作为IOC容器(已在生产环境中使用)

安装Autofac

我是使用Nuget安装两个Autofac:

  1. install-package Autofac
  2. install-package Autofac.Extensions.DependencyInjection

创建一个独立模块来实现动态依赖注入(也可以常规使用,我这里只讲解独立模块的依赖注入)

创建一个类,继承Autofac的模块类Module,然后重写父类的Load方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac;
using Levox.Framework.Core.Extensions;
using Levox.Framework.Core.Logger;
using Levox.Framework.Core.Models.Inject;
using Microsoft.AspNetCore.Mvc;
using Module = Autofac.Module;

namespace Levox.Framework.Core.ServiceInject
{
    /// <summary>
    /// ERP服务依赖注入   LastUpdateDate:2021-03-30 14:04:22.606  Author:Lingbug
    /// </summary>
    public class ErpServiceInjectModule : Module
    {
        /// <summary>
        /// 自定义注入   LastUpdateDate:2021-03-30 15:13:34.492  Author:Lingbug
        /// </summary>
        /// <param name="builder"></param>
        protected override void Load(ContainerBuilder builder)
        {
            //读取到所有需要依赖注入的程序集
            var assemblys = ServiceInjectUtil.GetLevoxAssemblys().ToArray();

            //注入服务
            LoadServices(builder, assemblys);
            //注入控制器
            LoadControllers(builder, assemblys);
        }

        /// <summary>
        /// 注入服务   LastUpdateDate:2021-03-30 14:44:15.803  Author:Lingbug
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assemblys"></param>
        private void LoadServices(ContainerBuilder builder, Assembly[] assemblys)
        {
            //标识类
            var baseType = typeof(IErpApplicationService);
            //读取到需要注入的服务类
            var appServiceTypes = assemblys.SelectMany(a => a.GetTypes()).Where(r => !r.IsInterface && baseType.IsAssignableFrom(r)).ToList();
            //注入记录
            var records = new List<Tuple<string, string>>();
            foreach (var type in appServiceTypes)
            {
                //读取服务实现的接口
                var iServiceTypes = type.GetInterfaces().ToArray();
                //注入类型
                string registerTypeStr = null;
                if (iServiceTypes.Contains(typeof(IErpTransientApplicationService)))
                {
                    //瞬时注入,且允许循环依赖
                    builder.RegisterType(type).AsImplementedInterfaces().InstancePerDependency().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
                    //赋值注入类型
                    registerTypeStr = "Transient";
                }
                else if (iServiceTypes.Contains(typeof(IErpScopedApplicationService)))
                {
                    //单次请求注入,且允许循环依赖
                    builder.RegisterType(type).AsImplementedInterfaces().InstancePerLifetimeScope().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
                    //赋值注入类型
                    registerTypeStr = "Scope";
                }
                else
                {
                    //单例注入,且允许循环依赖
                    builder.RegisterType(type).AsImplementedInterfaces().SingleInstance().PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
                    //赋值注入类型
                    registerTypeStr = "Singleton";
                }
                records.Add(new Tuple<string, string>(type.FullName, registerTypeStr));
            }
            //记录日志
            LoggerTestUtil.SimpleLog($"注入服务接口【count = {records.Count}】:{records.SerializeToJson()}");
        }

        /// <summary>
        /// 注入控制器   LastUpdateDate:2021-03-30 14:48:20.642  Author:Lingbug
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assemblys"></param>
        private void LoadControllers(ContainerBuilder builder, Assembly[] assemblys)
        {
            //控制器类
            var baseControllerType = typeof(ControllerBase);
            //注入控制器
            builder.RegisterAssemblyTypes(assemblys).Where(r => baseControllerType.IsAssignableFrom(r)).PropertiesAutowired();
        }
    }
}

修改Program类,使用Autofac容器

.UseServiceProviderFactory(new AutofacServiceProviderFactory())

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Autofac.Extensions.DependencyInjection;
using Levox.Framework.WebApi.Extensions;
using Levox.Framework.Model.Input;

namespace Levox.NewERP.WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                //使用Autofac容器
                .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureErpServices(services =>
                    {
                        //一行代码将框架注入到容器
                        services.AddErpInject(new AddErpInjectOption());
                    });
                    webBuilder.UseStartup<Startup>();
                });
    }
}

在Startup类中添加Autofac启动方法,在该方法中使用刚在自定义模块类,Autofac会自动调用

public void ConfigureContainer(ContainerBuilder builder) => builder.RegisterModule<ErpServiceInjectModule>();

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Levox.Framework.Model.Input;
using Levox.Framework.WebApi.Extensions;
using Autofac;
using Levox.Framework.Core.Logger;
using Levox.Framework.Core.ServiceInject;

namespace Levox.NewERP.WebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            //一行代码启动日志(注意配置文件路径必须为Config/log.config,且属性改为始终复制)
            LoggerInit.Init();
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {

        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //一行代码启动框架
            app.UseErpConfiguration(env, new UseErpConfigurationOption());
        }

        /// <summary>
        /// 定义此方法,框架自动调用注入所有系统服务   LastUpdateDate:2021-04-01 18:30:41.633  Author:Lingbug
        /// </summary>
        /// <param name="builder"></param>
        public void ConfigureContainer(ContainerBuilder builder) => builder.RegisterModule<ErpServiceInjectModule>();
    }
}

开发Autofac工具类,存储容器,在某些场景可以手动解析服务

开发Autofac工具类

using Autofac;
using Microsoft.AspNetCore.Http;

namespace Levox.Framework.Core.ServiceInject
{
    /// <summary>
    /// Autofac工具类   LastUpdateDate:2021-03-30 15:52:26.527  Author:Lingbug
    /// </summary>
    public static class ServiceInjectUtil
    {
        /// <summary>
        /// IOC容器   LastUpdateDate:2021-03-30 14:53:31.530  Author:Lingbug
        /// </summary>
        public static ILifetimeScope Container { get; set; }

        /// <summary>
        /// 解析服务   LastUpdateDate:2021-03-30 14:53:11.290  Author:Lingbug
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetService<T>() where T : class => Container.Resolve<T>();

        /// <summary>
        /// 获取服务(此次请求生命周期内)   LastUpdateDate:2021-03-30 14:54:02.594  Author:Lingbug
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetScopeService<T>() where T : class
        {
            //解析请求上下文
            var httpContextAccessor = GetService<IHttpContextAccessor>();
            //解析服务
            var service = httpContextAccessor.HttpContext.RequestServices.GetService(typeof(T));
            //返回
            return (T)service;
        }
    }
}

在Startup的Configure方法中拿到Autofac容器,并存储起来供工具类使用

ServiceInjectUtil.Container = app.ApplicationServices.GetAutofacRoot();//获取到容器并存储

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Levox.Framework.Model.Input;
using Levox.Framework.WebApi.Extensions;
using Autofac;
using Levox.Framework.Core.Logger;
using Levox.Framework.Core.ServiceInject;

namespace Levox.NewERP.WebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            //一行代码启动日志(注意配置文件路径必须为Config/log.config,且属性改为始终复制)
            LoggerInit.Init();
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {

        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //获取到容器并存储
            ServiceInjectUtil.Container = app.ApplicationServices.GetAutofacRoot();
            //一行代码启动框架
            app.UseErpConfiguration(env, new UseErpConfigurationOption());
        }

        /// <summary>
        /// 定义此方法,框架自动调用注入所有系统服务   LastUpdateDate:2021-04-01 18:30:41.633  Author:Lingbug
        /// </summary>
        /// <param name="builder"></param>
        public void ConfigureContainer(ContainerBuilder builder) => builder.RegisterModule<ErpServiceInjectModule>();
    }
}

Autofac核心Api总结

序号Api说明
1builder.RegisterType(type).AsImplementedInterfaces()将type注入到它的所有实现类中
2InstancePerDependency()瞬时注入
4InstancePerLifetimeScope()单次请求周期内注入
5SingleInstance()单例注入
6PropertiesAutowired()支持属性注入
7PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)支持属性注入且允许循环依赖
8builder.RegisterModule<ErpServiceInjectModule>()注入模块
9public void ConfigureContainer(ContainerBuilder builder) => builder.RegisterModule<ErpServiceInjectModule>();Startup定义方法模块注入,供Autofac自动调用
10ServiceInjectUtil.Container = app.ApplicationServices.GetAutofacRoot();Startup中获取Autofac容器,并存储
11.UseServiceProviderFactory(new AutofacServiceProviderFactory())Program使用Autofac
12builder.RegisterAssemblyTypes(assemblys).Where(r => typeof(ControllerBase).IsAssignableFrom(r)).PropertiesAutowired();注入控制器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值