.NET Core第12天_服務依賴注入_IoC容器生命週期_ConfigureServices

 

我們前面有示範幾種
服務注入
比方
注入MVC服務
services.AddMvc();

注入EF資料庫服務
services.AddDbContext<NorthwindContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("DbConnectonString")));


注入驗證服務
services.AddAuthentication();


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

關於依賴注入部分可以參考之前篇章


何謂IoC Container
Inversion of Control 控制反轉
把對於某個物件的控制權移轉給第三方容器,藉此原本兩物件互相依賴變更為
兩物件都依賴於第三方物件(俗稱容器)



在.net core內建的Container Service就是IServiceCollection這個型別
用於註冊服務到.net core容器中,預設支援constructor injection。





那事實上還有其餘很多方法


生命週期:
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.


ServiceType ClassIn the capacityof same HttpRequestDifferent Http Request
AddSingletonThe same Instance of repository servedThe same Instance of repository served
AddScopedSame InstanceDifferent Instance
AddTransientEvery time New InstanceEvery time New Instance


新增一個.net core Model-View-Controller專案
並添加一個新的控制器取名為ProductController


add new folder 命名為Database
並新增interface命名為 IProductService,定義要實作的兩個method 規格
分別是getInstanceId()跟getProductName()。
另外新增額外實作該介面的具體Class ProductService

IProductService.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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跟相應建構子傳入部分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

這裡可以看到使用Singleton效果物件ID都一樣
5071849d-8884-4ffb-94af-fd095a93985c



而且不管在重整呼叫同一個action method路由,物件id都不會變。



回到Startup.cs修改成
使用services.AddScoped<IProductService, ProductService>();
Scoped是每次Web請求會創建一個新實體,直到web請求結束就銷毀。


所以我們要模擬再次跳轉到這一個網址路由
我們可以到Views/Shared/_Layout.cshtml中調整多擴充一個訪問按鈕
來方便我們直接訪問就不用透過輸入網址方式




那就能發現當重整或是重呼叫一次同樣的url時候會有不同的object id


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


可以從第一次呼叫就發現回傳回來的兩個object id都不同
第二次也都是跟第一次完全不同的id

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












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/

留言

  1. Check also
    https://qawithexperts.com/article/asp-net/difference-between-addtransient-addscoped-and-addsingleton-i/404

    回覆刪除

張貼留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header