栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

asp.net core 3.1和 .Net 5.0中使用AutoFac作为IoC容器组件

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

asp.net core 3.1和 .Net 5.0中使用AutoFac作为IoC容器组件

一、为啥要使用第3方依赖注入框架 ?

1、微软官方提供的依赖注入框架已经很强大,一般情况无需第3方DI容器;

2、但是在一些特殊情况,需要第3方DI容器增强依赖注入功能,一般有如下几种情况:

(1) 基于名称的注入,基于Key的注入

    比如一个解决方案(一个webapi项目)同时作为多个MQ的消费者
(2)  属性注入
(3) 子容器
(4) 基于动态代理的 AOP

(5)整个应用程序级的生命周期;

二、普通的使用方法:

1、Nuget添加组件:Autofac.Extensions.DependencyInjection

2、Program里添加AutoFac:

UseServiceProviderFactory(new AutofacServiceProviderFactory())

using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup();
                });
    }
}

3、StartUp里添加一个方法

public void ConfigureContainer(ContainerBuilder builder)

4、与微软自带的几个常用的用法:

 public void ConfigureContainer(ContainerBuilder builder)
        {
            #region //1简单的使用--- 与默认DI容器相同的功能
                       //生命周期:默认,也就是瞬时模式==AddTransient
            // services.AddScoped();  --这个是微软自带的写法
            builder.RegisterType().As();

            //生命周期:默认,也就是瞬时模式==AddTransient
            builder.RegisterType().As().InstancePerDependency();

            //生命周期:Scope模式==AddScoped 
            builder.RegisterType().As().InstancePerLifetimeScope();

            //生命周期:单例,AddSingleton
            builder.RegisterType().As().SingleInstance();

            
            #endregion

          


        }

注意,写法还有有差别的,RegisterType的是类,As的是接口。

builder.RegisterType().As();

获取实例的方法与微软自带的容器获取实例方法一致。

比如在构造函数或者方法FromService里获取:

 private readonly ILogger _logger;
        private readonly IHostEnvironment _hostEnvironment;
        private readonly IServiceProvider _services;
        public HomeController(ILogger logger, IHostEnvironment hostEnvironment, IServiceProvider services)
        {
            _logger = logger;
            _hostEnvironment = hostEnvironment;
            _services = services;
        }



        public IActionResult Index3([FromServices] IEnumerable services)
        {
            Console.WriteLine("开始。。。。");
            foreach (var s in services)
            {
                Console.WriteLine($"获取到的实例为:{s.ToString()}:{s.GetHashCode()}");
            }


            return View();
        }
        public IActionResult Index2([FromServices] IHostEnvironment hostEnvironment, [FromServices] IStudent stu)
        {
            //1、通过构造函数注入,获取值
            string path = _hostEnvironment.ContentRootPath;

            //2、通过方法的FromServices注入进来,获取值
            string path2 = hostEnvironment.ContentRootPath;

            //通过GetRequiredService来检索服务
            var hostEnvironment2 = HttpContext.RequestServices.GetRequiredService();
            string path3 = hostEnvironment2.ContentRootPath;

            string name = stu.Change();
            int hashcode = stu.GetHashCode();



            return View();
        }

三、一些特别的用法:

1、基于名称的注入

在StartUp的 ConfigureContainer(ContainerBuilder builder)里注入:

 //基于名称的注入
 builder.RegisterType().Named("muxue").SingleInstance();

获取实例的方法,有2种方法:

(1) IServiceProvider里获取AutoFac根容器再进行获取实例;

(2)使用AutoFac自带的ILifetimeScope获取实例;

代码如下:

 private readonly ILogger _logger;
        private readonly IHostEnvironment _hostEnvironment;
        private readonly IServiceProvider _services;
        public HomeController(ILogger logger, IHostEnvironment hostEnvironment, IServiceProvider services)
        {
            _logger = logger;
            _hostEnvironment = hostEnvironment;
            _services = services;
        }

        /// 
        /// 基于名称的注入-的获取(沐雪原创)
        /// 
        /// 
        /// 
        public IActionResult Index([FromServices] ILifetimeScope service)
        {
            Console.WriteLine("开始取对象。。。。");
            //使用IServiceProvider 的方法
            // var service= _services.GetAutofacRoot();
            var stu = service.ResolveNamed("myName");
            Console.WriteLine($"获取到的实例为:{stu.ToString()}:{stu.GetHashCode()}");
            return View();
        }

2、基于Key的注入:跟基于名称的注入类似,我们在使用RabbitMQ,一个项目有多个消费者的情况使用的demo 

            builder.Register((c, p) => RabbitHutch.CreateBus(c.Resolve().GetConnectionString("MQ1")))
                   .Keyed("MQ1")
                   .SingleInstance();
            builder.Register((c, p) => RabbitHutch.CreateBus(c.Resolve().GetConnectionString("MQ2")))
                  .Keyed("MQ2")
                  .SingleInstance();

获取实例的方法:

var bus = _services.GetAutofacRoot().ResolveKeyed("MQ1");

3、基于属性的注入(这个在微软自带的IOC好像也有类似的写法,比如,类里需要一个Configuration的一个节点值,可以先注册该节点值,然后就可以在类里直接使用了。)

也就是一个类A里有一个属性类B,代码如下:

    public class StudentService: IStudentService
    {
        public AddressService addrService { get; set; }

        public void ShowCode()
        {
            Console.WriteLine($"StudentService.ShowCode:{GetHashCode()},addrService 是否为空:{addrService == null}");
        }
    }


    public class AddressService
    { 
        
    }

addrService是StudentService的一个属性值;

注册的时候,需要先将addrService注册,在使用属性注册的方式注册StudentService;

   #region 属性注册
            builder.RegisterType();
            builder.RegisterType().As().PropertiesAutowired();
            #endregion

四、AutoFac的切面编程--拦截器AOP的使用

第一眼看到拦截器AOP功能,我还以为是个鸡肋,.NetCore都已经有了那么强大的Filter作为AOP拦截器,为啥AutoFac还有这个玩意?

        后来才发现,是自己想错了。AutoFac的拦截器,拦截的是注册在容器里的服务的实例里的方法。有点绕,简单说,他拦截的是方法,是一个实例的方法,是依赖注入注册在容器里的服务对应的实例。  而Filter则是对控制器Controller/Action的AOP的实现。两者拦截的对象不同。

AutoFac的拦截器是基于大名鼎鼎的Castle.Core来完成的。也就是Castle.Core里的一个动态代理DynamicProxy。

我们现在看下代码的实现!

1、Nuget新增加一个组件

Autofac.Extras.DynamicProxy

2、搞一个自定义的拦截器

using Castle.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication1
{
    /// 
    /// 沐雪-自定义一个拦截器
    /// 
    public class MyInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            Console.WriteLine("----- 拦截器开始啦 -------");
            //方法的真正执行
            invocation.Proceed();
            Console.WriteLine("----- 拦截器结束啦 -------rn");
        }
    }
}

该拦截器继承自IInterceptor接口,我们要显示实现该接口的方法Intercept,注意里面的一句代码

  invocation.Proceed();

这是调用真实方法。

3、开始注册了,将我们自定义的拦截器,以及要拦截的服务(接口和对象)都注册进来。

在ConfigureContainer 方法里写:

 public void ConfigureContainer(ContainerBuilder builder)
        {
            

            //拦截器
            builder.RegisterType();
            //IStudent需要这个拦截器
            builder.RegisterType().As().InterceptedBy(typeof(MyInterceptor)).EnableInterfaceInterceptors();


        }

我们再看下IStudent里的部分代码(demo代码):

 public interface IStudent
    {

       string   Change();
        string Change2();

    }
    public class Student : IStudent
    {
        public string name { get; set; } = "小王";
        public Student()
        {


        }

        public Student(string initName)
        { 
            name = initName;
        }

        public string Change()
        {
            Console.WriteLine("在change方法里");
            name += "002";
            return name;
        }
        public string Change2()
        {
            Console.WriteLine("在change2方法里");
            name += "007";
            return name;
        }
    }

4、最后一步,获取该实例,并且执行该实例的相应方法:

        /// 
        /// 测试AutoFac拦截器
        /// 
        /// 
        /// 
        public IActionResult Index([FromServices] IStudent services)
        {
            Console.WriteLine("rn沐雪大神爱吃鱼--Start。。。。rn"); 
            Console.WriteLine($"获取到的实例为:{services.ToString()}:{services.GetHashCode()}rn");
            services.Change();
            Console.WriteLine("沐雪大神爱吃鱼--已经吃了一条。。。。rn");
            services.Change2();

            Console.WriteLine("沐雪大神爱吃鱼--吃完啦。。。。");
            return View();
        }

直接结果如下图:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/909528.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号