1. 程式人生 > >ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自帶的IOC容器)

ASP.NET Core中使用IOC三部曲(一.使用ASP.NET Core自帶的IOC容器)

https://www.cnblogs.com/GuZhenYin/p/8297145.html

 

今天我們主要講講如何使用自帶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次訪問,都使用的同一個物件.也符合我們的預期.