• ASP.NET Core框架学习之依赖注入


    ASP.NET Core支持依赖项注入(DI)软件设计模式,这是一种用于在类及其依赖项之间实现控制反转(IoC)的技术

    引用nuget包

    .net core使用了接口与实现分离的设计模式,这样的好处是第三方的Ioc容器只需要引用Microsoft.Extensions.DependencyInjection.Abstractions包,并实现其中的接口,就可以与.net core框架完美兼容了。

    Microsoft.Extensions.DependencyInjection.Abstractions
    Microsoft.Extensions.DependencyInjection 

    简单示例 

      声明接口及其实现类

    //声明一个接口
    public interface IVipService    
    {}
    //声明IVipService接口的实现类
    public class VipService : IVipService 
    {} 

      在Startup.cs的ConfigureServices方法中将接口实现添加到Ioc容器

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IVipService, VipService>();
        services.AddControllers();
    }

      通过构造函数注入: 

    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly IVipService _vipService;
    
        public WeatherForecastController( IVipService vipService)  //在构造函数中注入IVipService接口
        {
            _vipService = vipService;
        }
    
        [HttpGet]
        public string Get( )
        {
            return _vipService.GetHashCode().ToString();
        }
    }

      通过方法注入:

    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
    
        [HttpGet]
        public string Get([FromServices]IVipService vipService)  // 在方法入参中使用[FromServices]特性注入IVipService接口
        {
            return vipService.GetHashCode().ToString();
        }
    }  

       这样我们就完成了一个依赖注入的简单示例,当有请求路由到WeatherForecastController控制器时,依赖注入框架会自动将Ioc容器中的实现类创建好注入到WeatherForecastController中,这样WeatherForecastController也就不在依赖于IVipService的具体实现类,如果需要更换IVipService的实现,那么只需要修改 services.AddScoped<IVipService, VipService>(); 这一段代码就可以了。

    生命周期  

       .net core的依赖注入框架支持创建三种不同生命周期的服务。

    public enum ServiceLifetime
    {
        // 单例模式
        Singleton = 0,
        // 作用域模式
        Scoped = 1,
        // 瞬时模式
        Transient = 2
    }
      Singleton :单例模式,在整个应用程序的生命周期内,每次调用都使用同一个实例。
      Scoped :作用域模式,在同一个作用域内,每次调用都使用同一个实例。
      Transient:瞬时模式,每次调用都会创建一个新的实例。
    三种生命周期,使用下面三种不同的方法注入
    services.AddSingleton<IVipService, VipService>();
    services.AddScoped<IVipService, VipService>();
    services.AddTransient<IVipService, VipService>();

       实现了IDisposable接口并且由容器创建的实例由容器主动释放,其他的实例生命周期结束后由GC释放。

    泛型模板注入

    services.AddSingleton(typeof(IVipService<>),typeof(VipService<>)); 

    工厂注入(用以处理一些特殊的情况)

    //一个接口 两个实现类 
    public interface IVipService
    {
    }
    
    public class ErpVipService : IVipService
    {
    }
    
    public class WxVipService : IVipService
    {
    }
    //将工厂包装一层
    public class VipServiceFactory
    {
        private readonly Func<int, IVipService> _func;
        public VipServiceFactory(Func<int, IVipService> func)
        {
            _func = func;
        }
        public IVipService GetInstence(int type)
        {
            return _func(type);
        }
    }
    //注入扩展类
    public static class VipServiceExtensions
    {
        public static IServiceCollection AddVipService(this IServiceCollection services)
        {
            services.AddScoped<ErpVipService>();
            services.AddScoped<WxVipService>();
            //通过工厂方式根据类型条件决定创建哪个实现类
            services.AddScoped(serviceProvider =>
            {
                Func<int, IVipService> func = type =>
                {
                    if (type == 0) return (IVipService)serviceProvider.GetService<ErpVipService>();
                    else
                        return (IVipService)serviceProvider.GetService<WxVipService>();
                };
                return func;
            });
            services.AddScoped<VipServiceFactory>();
            return services;
        }
    }

      在ConfigureServices中注入

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddVipService();
        services.AddControllers();
    }

      控制器中使用

    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly VipServiceFactory _vipServiceFactory;
        
        //将工厂类注入到构造函数
        public WeatherForecastController(VipServiceFactory vipServiceFactory)
        {
            _vipServiceFactory = vipServiceFactory;
        }
    
        [HttpGet]
        public string Get( )
        {
          return   _vipServiceFactory.GetInstence(0).GetHashCode().ToString();
        }
    }

    手写Ioc容器

      自己手撸的一个简单Ioc容器实现,只是用以了解Ioc的内部实现原理,不喜勿喷。

      地址:https://github.com/Jasonbourne723/eShop/blob/main/src/Tests/dotnet.Console.Test/Program.cs

    开源框架推荐

      Scrutor: Kristian Hellang 大神写的一个基于Microsoft.Extensions.DependencyInjection的一个扩展库,主要是为了简化我们对DI的操作。
      Autofac: .NET领域最为流行的IoC框架之一,功能多,性能好,易学习。 

     官方文档

      https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

  • 相关阅读:
    asp.net mvc上传图片案例
    kafka 常用参数
    play framework 笔记
    调试 kafka manager 源码
    kafka AdminClient 闲时关闭连接
    kafka 心跳和 rebalance
    kafka producer batch 发送消息
    kafka producer 发送消息简介
    zk 的配额
    kafka consumer 指定 offset,进行消息回溯
  • 原文地址:https://www.cnblogs.com/jasonbourne3/p/14611684.html
Copyright © 2020-2023  润新知