本文主要是詳解一下在ASP.NET Core中,自帶的IOC容器相關的使用方式和注入類型的生命周期.
這里就不詳細的贅述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度.
目錄
ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自帶的IOC容器)
ASP.NET Core中使用IOC三部曲(二.采用Autofac來替換IOC容器,並實現屬性注入)
ASP.NET Core中使用IOC三部曲(三.采用替換后的Autofac來實現AOP攔截)
今天我們主要講講如何使用自帶IOC容器,emm..雖然自帶的功能不是那么強大,但是勝在輕量級..而且..不用引用別的庫..
在新的ASP.NET Core中,大量的采用了依賴注入的方式來編寫代碼.
比如,在我們的Startup類中的ConfigureServices里,就可以看到:
AddMvc AddDbContext 包括我們之前目錄游覽用到的AddDirectoryBrowser..
都是框架提供好的服務,我們直接注入就可以使用了.
1.如何注入自己的服務
下面我們就來講講如何注入自己的服務.
首先,我們編寫我們自己的測試服務如下:
public class TestService: ITestService { public TestService() { MyProperty = Guid.NewGuid(); } public Guid MyProperty { get; set; } public List<string> GetList(string a) { return new List<string>() { "LiLei", "ZhangSan", "LiSi" }; } }
編寫對應的接口代碼如下:
public interface ITestService { Guid MyProperty { get; } List<string> GetList(string a); }
然后,我們要在Startup類引用 Microsoft.Extensions.DependencyInjection(ps,這命名已經很直白了..微軟..擴展...依賴注入 - - ,)
修改ConfigureServices方法,如下:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext<BloggingContext>(); //這里就是注入服務 services.AddTransient<ITestService, TestService>(); services.AddDirectoryBrowser(); }
AddTransient就是注入的方法之一,泛型參數,前面一個是你服務的接口,第二個是服務的實現類..
這樣,我們就完成了初步的注入操作.
那么我們如何使用我們注入的服務呢?
我們到控制器,編寫代碼如下:
public class DITestController : Controller { private readonly ITestService _testService; public DITestController(ITestService testService) { _testService = testService; } public IActionResult Index() { ViewBag.date = _testService.GetList(""); return View(); } }
注入的方式一般有三種,構造函數注入, 方法注入,屬性注入..微軟自帶的這個IOC容器,默認采用了構造函數注入的方式(不支持屬性注入,不過可以用第三方容器替換來實現,下篇講)
我們編寫我們的index視圖如下:
@{ ViewData["Title"] = "Index"; } <h2>Index</h2> @foreach (var item in ViewBag.date) { <h2>@item</h2> }
最終效果如下:
2.注入服務的生命周期
微軟給自行注入的服務,提供了3種生命周期.
Transient(瞬時的)
每次請求時都會創建的瞬時生命周期服務。這個生命周期最適合輕量級,無狀態的服務。
Scoped(作用域的)
在同作用域,服務每個請求只創建一次。
Singleton(唯一的)
全局只創建一次,第一次被請求的時候被創建,然后就一直使用這一個.
如何使用這三種生命周期呢?.我們直接在注入的時候用不同的方法就行了,代碼如下:
services.AddTransient<ITestService, TestService>(); services.AddScoped<ITestService2, TestService2>(); services.AddSingleton<ITestService3, TestService3>();
下面,我們就來測試一下這三種生命周期的具體生成情況
我們編寫三個不同名稱的接口如下:
public interface ITestService { Guid MyProperty { get; } List<string> GetList(string a); } public interface ITestService2 { Guid MyProperty { get; } List<string> GetList(); } public interface ITestService3 { Guid MyProperty { get; } List<string> GetList(); }
然后用3個類來分別實現他們.
public class TestService: ITestService { public TestService() { MyProperty = Guid.NewGuid(); } public Guid MyProperty { get; set; } public List<string> GetList(string a) { return new List<string>() { "LiLei", "ZhangSan", "LiSi" }; } } public class TestService2 : ITestService2 { public TestService2() { MyProperty = Guid.NewGuid(); } public Guid MyProperty { get; set; } public List<string> GetList() { return new List<string>() { "LiLei", "ZhangSan", "LiSi" }; } } public class TestService3 : ITestService3 { public TestService3() { MyProperty = Guid.NewGuid(); } public Guid MyProperty { get; set; } public List<string> GetList() { return new List<string>() { "LiLei", "ZhangSan", "LiSi" }; } }
每個實現類的構造函數中,我們都產生了一個新的guid,通過這個GUID,我們可以判斷這個類到底重新執行過構造函數沒有.
我們編寫注入代碼如下:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext<BloggingContext>(); services.AddTransient<ITestService, TestService>(); services.AddScoped<ITestService2, TestService2>(); services.AddSingleton<ITestService3, TestService3>(); services.AddDirectoryBrowser(); }
我們修改控制器如下:
public class DITestController : Controller { private readonly ITestService _testService; private readonly ITestService2 _testService2; private readonly ITestService3 _testService3; public DITestController(ITestService testService, ITestService2 testService2, ITestService3 testService3) { _testService = testService; _testService2 = testService2; _testService3 = testService3; } //這里采用了Action注入的方法 public IActionResult Index([FromServices]ITestService testService11, [FromServices]ITestService2 testService22) { ViewBag.date = _testService.GetList(""); ViewBag.guid = _testService.MyProperty; ViewBag.guid11 = testService11.MyProperty; ViewBag.guid2 = _testService2.MyProperty; ViewBag.guid22 = testService22.MyProperty; ViewBag.guid3 = _testService3.MyProperty; return View(); } }
這里說明一下,我們采用了Action注入的方法,新注入了一個ITestService2 ,來保證2個ITestService2 在同一個作用域.
我們編寫相關的index頁面,來展示這些信息如下:
@{ ViewData["Title"] = "Index"; } <h2>Index</h2> @foreach (var item in ViewBag.date) { <h2>@item</h2> } <h1>瞬時的:@ViewBag.guid</h1> <h1>瞬時的2:@ViewBag.guid11</h1> <h1>作用域的:@ViewBag.guid2</h1> <h1>作用域的2:@ViewBag.guid22</h1> <h1>全局唯一的:@ViewBag.guid3</h1>
我們運行代碼,第一次訪問,效果如下:
我們發現瞬時生命周期的,2次生成的GUID都不一致,說明對象不是同一個.
然而作用域生命周期的,因為在同一個作用域下,2次使用服務的GUID都是一致的,說明用的同一個對象.
我們直接刷新頁面進行第二次訪問.
效果如下:
瞬時的和作用域的,都繼續符合我們的預期,
全局唯一生命周期的和上面第一次訪問的GUID保持一致.說明2次訪問,都使用的同一個對象.也符合我們的預期.
本篇到此就結束了,下篇我們講解,如何使用第三方的Autofac來替換我們默認的IOC容器,並且使用Autofac的屬性注入,來注入我們的服務. 喜歡的請點個推薦和關注,~有問題也希望各位批評指正~.