循序渐进学.Net Core Web Api开发系列【11】:依赖注入

摘要:
publicinterfaceILogService{voidLogInfomation;}publicclassMyLogService:ILogService{voidILogService.LogInfomation{Console.WriteLine;}}注册该服务publicvoidConfigureServices{services.AddMvc();services.AddCors();services.AddSingleton();}注册成功,我们在Controller中使用该服务:publicclassArticleController:Controller{privatereadonlyILogService_myLog;publicArticleController{_myLog=myLog;}[HttpGet]publicvoidTestLogger{_myLog.LogInfomation;return;}}简单分析一下:1、首先通过services.AddSingleton方法向依赖注入容器登记注册MyLogService;2、在构建Controller时,根据其构造函数类型遍历其输入参数,在依赖注入容器中找到该对象并作为实参传递给构造方法。

系列目录

循序渐进学.Net Core Web Api开发系列目录

本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi

一、概述

本篇介绍如何采用依赖注入的方式创建和使用对象,主要从应用层面进行描述,不涉及具体的内部原理。

二、演练

假设要做一个日志服务的类,它实现在控制台打印出带时间信息的日志信息。

首先定义该服务的接口与实现类。

   public interfaceILogService
    {
        void LogInfomation(stringinfo);
    }
    public classMyLogService : ILogService
    {
        void ILogService.LogInfomation(stringinfo)
        {
            Console.WriteLine($"==> MyLogService : {DateTime.Now.ToString()}:{info}");
        }
    }

注册该服务

public voidConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddCors();
           services.AddSingleton<ILogService, MyLogService>();
        }

注册成功,我们在Controller中使用该服务:

public classArticleController : Controller
    {       
private readonlyILogService _myLog; public ArticleController(ILogService myLog) { _myLog =myLog; } [HttpGet("logger")] public void TestLogger(stringlogger) { _myLog.LogInfomation("hahaha"); return; } }

简单分析一下:

1、首先通过services.AddSingleton方法向依赖注入容器登记注册MyLogService;

2、在构建Controller时,根据其构造函数类型遍历其输入参数,在依赖注入容器中找到该对象并作为实参传递给构造方法。

三、生命周期问题

注册一个服务,根据生命周期需要的不同,有下面三种方式:

services.AddSingleton<ILogService, MyLogService>();
services.AddScoped<ILogService, MyLogService>();
ervices.AddTransient<ILogService, MyLogService>();

三种注册方式分别对应三种生命周期

1)Singleton:单例服务,从当前服务容器中获取这个类型的实例永远是同一个实例;

2)Scoped:每个作用域生成周期内创建一个实例;

3)Transient:每一次请求服务都创建一个新实例;

对我们的日志进行改造,让其在构建时生成一个ID,通过观察其guid变化可以理解这三种生命周期的区别。

public classMyLogService : ILogService
    {
        publicGuid _guid;
        publicMyLogService()
        {
            _guid =Guid.NewGuid();
        }
        void ILogService.LogInfomation(stringinfo)
        {
            Console.WriteLine($"==> MyLogService : My Guid is :{_guid}");
            Console.WriteLine($"==> MyLogService : {DateTime.Now.ToString()}:{info}");
        }
    }

四、通过扩展方法注册服务

通过对IServiceCollection增加扩展方法来注册服务

public static classMyLogServiceCollectionExtensions
    {
        public static void AddMyLog(thisIServiceCollection services)
        {
            services.AddSingleton<ILogService, MyLogService>();
        }
    }

这样,使用者的注册代码可以修改为:

public voidConfigureServices(IServiceCollection services)
{   
services.AddMvc();
  services.AddCors();
services.AddMyLog(); 
}

可见AddMvc、AddCors等也是向容器注入服务。

        public static IMvcBuilder AddMvc(thisIServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException("services");
            }
            IMvcCoreBuilder mvcCoreBuilder =MvcCoreServiceCollectionExtensions.AddMvcCore(services);
            MvcApiExplorerMvcCoreBuilderExtensions.AddApiExplorer(mvcCoreBuilder);
            MvcCoreMvcCoreBuilderExtensions.AddAuthorization(mvcCoreBuilder);
            MvcServiceCollectionExtensions.AddDefaultFrameworkParts(mvcCoreBuilder.PartManager);
            MvcCoreMvcCoreBuilderExtensions.AddFormatterMappings(mvcCoreBuilder);
            MvcViewFeaturesMvcCoreBuilderExtensions.AddViews(mvcCoreBuilder);
            MvcRazorMvcCoreBuilderExtensions.AddRazorViewEngine(mvcCoreBuilder);
            MvcRazorPagesMvcCoreBuilderExtensions.AddRazorPages(mvcCoreBuilder);
            TagHelperServicesExtensions.AddCacheTagHelper(mvcCoreBuilder);
            MvcDataAnnotationsMvcCoreBuilderExtensions.AddDataAnnotations(mvcCoreBuilder);
            MvcJsonMvcCoreBuilderExtensions.AddJsonFormatters(mvcCoreBuilder);
            MvcCorsMvcCoreBuilderExtensions.AddCors(mvcCoreBuilder);
            return newMvcBuilder(mvcCoreBuilder.Services, mvcCoreBuilder.PartManager);
        }
View Code

五、几个问题

1、如果多次注册会怎样

可以多次注册同一种生命周期的类,如下是可以的:

services.AddSingleton<ILogService, MyLogService>();
services.AddSingleton<ILogService, MyLogService>();
services.AddSingleton<ILogService, MyLogService>();

但下面这个代码不行:

services.AddSingleton<ILogService, MyLogService>();
services.AddScoped<ILogService, MyLogService>();

2、如何获取已经注册的服务列表

通过ServicesProvider可以获取服务列表

services.AddMyLog();
            services.AddMyLog();
            services.AddMyLog();
            var provider =services.BuildServiceProvider();
            var servicesList = provider.GetServices< ILogService >();
            foreach (var service inservicesList)
            {
                Console.WriteLine("service:" +service.ToString());
            }

以上代码输出3条记录。

但下面的代码只输出一条记录:

services.AddCors();
            services.AddCors();
            services.AddCors();          
            var provider =services.BuildServiceProvider();
            var servicesList = provider.GetServices<ICorsService>();
            foreach (var service inservicesList)
            {
                Console.WriteLine("service:" +service.ToString());
            }

具体原因看一下源码就清楚了:

public static IServiceCollection AddCors(thisIServiceCollection services)
{
    if (services == null)
    {
        throw new ArgumentNullException("services");
    }
    services.TryAdd(ServiceDescriptor.Transient<ICorsService, CorsService>());
returnservices;
}
    public static void TryAdd(thisIServiceCollection collection, ServiceDescriptor descriptor)
     {
            if (!collection.Any((ServiceDescriptor d) => d.ServiceType ==descriptor.ServiceType))
            {
                collection.Add(descriptor);
            }
     }

所以我们应该按照这个方法修改我们的AddMyLog方法。

免责声明:文章转载自《循序渐进学.Net Core Web Api开发系列【11】:依赖注入》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows 安装配置 JIRA八、敏捷开发框架-设计开发小助手,提升开发效率下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.net core api +swagger(一个简单的入门demo 使用codefirst+mysql)

前言: 自从.net core问世之后,就一直想了解。但是由于比较懒惰只是断断续续了解一点。近段时间工作不是太忙碌,所以偷闲写下自己学习过程。慢慢了解.net core 等这些基础方面学会之后再用.net core写一个项目,前期文章都是为之后的项目做准备。同时也希望这些基础文章能帮助更多的想入手 .net core的小白。(文中如有不正确地方欢迎各位指正...

.NET Core 中基于 IHostedService 实现后台定时任务

.NET Core 2.0 引入了 IHostedService ,基于它可以很方便地执行后台任务,.NET Core 2.1 则锦上添花地提供了 IHostedService 的默认实现基类 BackgroundService ,在这篇随笔中分别用 Web 与 Console 程序体验一下。 首先继承 BackgroundService 实现一个 Tim...

ABP 框架

ABP 框架基础知识 ABP是一个开源且文档友好的应用程序框架。ABP不仅仅是一个框架,它还提供了一个最徍实践的基于领域驱动设计(DDD)的体系结构模型,可以支持 .net framework和 .net core两种技术流派。 ABP 框架特点 依赖注入,这个部分使用 Castle windsor (依赖注入容器)来实现依赖注入,这个也是我们经常使用I...

IDEA+SpringBoot整合Swagger2创建API文档

------------恢复内容开始------------ 1.创建SpringBoot项目 2.选择快捷方式创建springboot项目          3.工程文件树形图  4.pom.xml中导入Swagger依赖  代码如下: 1 <dependency> 2 <groupId&...

【翻译】Flink Table API &amp;amp; SQL 自定义 Source &amp;amp; Sink

本文翻译自官网:https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/table/sourceSinks.html TableSource 提供访问存储在外部系统(数据库、key-value 存款,消息队列)或文件中的数据的权限。TableSource 在 TableEnviron...

图形数据库 Neo4j 开发实战

本人用途:知识图谱 neo4j:图状数据库 官网地址:http://neo4j.com/docs/java-reference/current/ 中文API:https://www.w3cschool.cn/neo4j/neo4j_building_blocks.html Neo4j 简介 数据存储一般是应用开发中不可或缺的组成部分。应用运行中产生的...