.NET Core第12天_服务依赖注入_IoC容器生命周期_ConfigureServices

我们前面有示范几种
服务注入
比方
注入MVC服务
services.AddMvc();

注入EF资料库服务
services.AddDbContext(options =>options.UseSqlServer(Configuration.GetConnectionString("DbConnectonString")));

注入验证服务
services.AddAuthentication();

全写在Startup.cs的
public void ConfigureServices(IServiceCollection services)方法当中

关於依赖注入部分可以参考之前篇章
Dependency Injection原理与实践(一)

何谓IoC Container
Inversion of Control 控制反转
把对於某个物件的控制权移转给第三方容器,藉此原本两物件互相依赖变更为
两物件都依赖於第三方物件(俗称容器)
https://ithelp.ithome.com.tw/upload/images/20210914/20107452ah6qRQkqmi.png

在.net core内建的Container Service就是IServiceCollection这个型别
用於注册服务到.net core容器中,预设支援constructor injection。

那事实上还有其余很多方法
https://ithelp.ithome.com.tw/upload/images/20210914/20107452JrjwP7gJdE.png

生命周期:
Transient:每次被请求都会创建新的实体
Transient objects are always different; a new instance is provided to every controller and every service.

Scoped:每次Web请求会创建一个新实体,直到web请求结束就销毁。
Scoped objects are the same within a request, but different across different requests.

Singleton:一旦被创建实体就会持续一直用,直到应用停止才销毁。
Singleton objects are the same for every object and every request.

https://ithelp.ithome.com.tw/upload/images/20210914/20107452HmfXS4wMKU.png

新增一个.net core Model-View-Controller专案
并添加一个新的控制器取名为ProductController
https://ithelp.ithome.com.tw/upload/images/20210914/20107452kZkkuaMroX.png

add new folder 命名为Database
并新增interface命名为 IProductService,定义要实作的两个method 规格
分别是getInstanceId()跟getProductName()。
另外新增额外实作该介面的具体Class ProductService
https://ithelp.ithome.com.tw/upload/images/20210914/20107452jcMBvwg135.png

IProductService.cs

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

namespace ContainerServiceMethods.Database
{
    public interface IProductService
    {
        string getInstanceId();
        string getProductName(int id);
    }
}

ProductService.cs

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

namespace ContainerServiceMethods.Database
{
    public class ProductService : IProductService
    {
        string InstanceId { get; set; }
        public ProductService()
        {
            InstanceId = Guid.NewGuid().ToString();
        }
        public string getInstanceId()
        {
            return InstanceId;
        }
        public string getProductName(int id)
        {
            return "爱之味-牛奶花生";
        }
    }
}

在这我们为了验证物件是否为旧的还是新创建出来的因此透过
於建构子设定唯一的Guid来识别。

在ProductService中调整action method跟相应建构子传入部分

using ContainerServiceMethods.Database;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ContainerServiceMethods.Controllers
{
    public class ProductController : Controller
    {
        IProductService _p1;
        IProductService _p2;

        public ProductController(IProductService p1, IProductService p2)
        {
            _p1 = p1;
            _p2 = p2;
        }

        public string[] GetInstances()
        {
            string[] data = new string[2];
            data[0] = _p1.getInstanceId();
            data[1] = _p2.getInstanceId();
            return data;
        }
    }
}

於Startup.cs
public void ConfigureServices(IServiceCollection services)方法

我们去注入刚创建好的自订的服务
使用services.AddSingleton<IProductService, ProductService>();
第一个参数传入interface第二个则是实作该interface的class
https://ithelp.ithome.com.tw/upload/images/20210914/20107452dOElRewwWV.png

这里可以看到使用Singleton效果物件ID都一样
5071849d-8884-4ffb-94af-fd095a93985c

https://ithelp.ithome.com.tw/upload/images/20210914/20107452nKH3SZlly3.png

而且不管在重整呼叫同一个action method路由,物件id都不会变。

回到Startup.cs修改成
使用services.AddScoped<IProductService, ProductService>();
Scoped是每次Web请求会创建一个新实体,直到web请求结束就销毁。

所以我们要模拟再次跳转到这一个网址路由
我们可以到Views/Shared/_Layout.cshtml中调整多扩充一个访问按钮
来方便我们直接访问就不用透过输入网址方式

https://ithelp.ithome.com.tw/upload/images/20210914/20107452P0KwdPiAcO.png

那就能发现当重整或是重呼叫一次同样的url时候会有不同的object id

https://ithelp.ithome.com.tw/upload/images/20210914/20107452EcFjf6SVtK.png

回到Startup.cs修改成
改使用 services.AddTransient<IProductService, ProductService>();

可以从第一次呼叫就发现回传回来的两个object id都不同
第二次也都是跟第一次完全不同的id
https://ithelp.ithome.com.tw/upload/images/20210914/20107452Jhx3L1EFol.png

原因在於Transient
每次要求元件时就建立一个新的,永不共用。

本篇同步发表至个人部落格
https://coolmandiary.blogspot.com/2021/07/net-core12iocconfigureservices.html

Ref:
What is the AddSingleton vs AddScoped vs Add Transient C# Asp.net Core?
https://www.tutorialspoint.com/what-is-the-addsingleton-vs-addscoped-vs-add-transient-chash-asp-net-core

Understanding AddTransient Vs AddScoped Vs AddSingleton In ASP.NET Core
https://www.c-sharpcorner.com/article/understanding-addtransient-vs-addscoped-vs-addsingleton-in-asp-net-core/

AddTransient, AddScoped and AddSingleton Services Differences
https://stackoverflow.com/questions/38138100/addtransient-addscoped-and-addsingleton-services-differences

IOC(控制反转) , DI(依赖注入) 深入浅出~~
https://dotblogs.com.tw/daniel/2018/01/17/140435

笔记 - 不可不知的 ASP.NET Core 依赖注入
https://blog.darkthread.net/blog/aspnet-core-di-notes/


<<:  (Day14) 闭包 (Closure) 介绍

>>:  [Day 2] 快来探索AI的世界

Day 5 - 类神经网路可做什麽

假设 y是结果(如股票价格) , x是变数(如进料成本,薪资成本......等) , 以分类或回归分...

[Day14] 建立订单交易API_7

更新一下get_iv这支程序 def get_iv(nonce): sha_nonce_value ...

Day 3 Compose UI Hello World

嗨!大家好,我是Teng: 今年的疫情蛮严重的,希望大家都过得安好, 希望疫情快点过去,能回到一些线...

Day_01: 让 Vite 来开启你的Vue 前言

Hi Da Gei Ho~ 初次见面,我是Winnie~ 我是一位刚转职六个月的菜鸟前端(前身是网页...

前端工程学习日记第三天

小技巧:ul>li*3 打出来 可以用emmet快速做出 昨日疑问:我的HTML为何没有快速工...