我們前面有示範幾種
服務注入
比方
注入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 控制反轉
把對於某個物件的控制權移轉給第三方容器,藉此原本兩物件互相依賴變更為
兩物件都依賴於第三方物件(俗稱容器)
在.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.
新增一個.net core Model-View-Controller專案
並添加一個新的控制器取名為ProductController
add new folder 命名為Database
並新增interface命名為 IProductService,定義要實作的兩個method 規格
分別是getInstanceId()跟getProductName()。
另外新增額外實作該介面的具體Class ProductService
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
這裡可以看到使用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
每次要求元件時就建立一個新的,永不共用。
本篇同步發表至個人部落格
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/