<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      .NET Core ASP.NET Core Basic 1-2

      本節(jié)內(nèi)容為控制反轉(zhuǎn)與依賴(lài)注入

      簡(jiǎn)介

      控制反轉(zhuǎn)IOC


      這個(gè)內(nèi)容事實(shí)上在我們的C#高級(jí)篇就已經(jīng)有所講解,控制反轉(zhuǎn)是一種設(shè)計(jì)模式,你可以這樣理解控制反轉(zhuǎn),假設(shè)有一個(gè)人他有一部A品牌手機(jī),他用手機(jī)進(jìn)行聽(tīng)歌、打游戲,那么你可以創(chuàng)建一個(gè)手機(jī)類(lèi)和一個(gè)人類(lèi)
      class APhone : IPhone { public string Owner{get;set;} public Phone(string own)
      { Owner = own; } void Play() { //省略 } void Music() { //省略 } } class Man {
      public string Name{get;set;} void Game() { var p = new APhone(Name); p.Play();
      } }

      事實(shí)上這段代碼的耦合度是比較高的?它使用的是正轉(zhuǎn),也就是我需要什么東西的時(shí)候我就自己創(chuàng)建一個(gè)這個(gè)東西。為什么說(shuō)他不好呢,如果有一天這個(gè)人決定再也不使用A品牌手機(jī)了,他決定以后只使用B品牌。那么也就意味著整個(gè)的Man類(lèi)使用過(guò)APhone類(lèi)的地方都需要更改。這是一個(gè)非常麻煩的事情,我們這個(gè)時(shí)候就需要運(yùn)用我們的IOC控制反轉(zhuǎn)了。我們將實(shí)例或者是需要使用的對(duì)象的創(chuàng)建交給你的調(diào)用者,自己只負(fù)責(zé)使用,其它人丟給你依賴(lài)的這個(gè)過(guò)程理解為注入。


      控制反轉(zhuǎn)的核心就是——原本我保存使用我自己的東西,現(xiàn)在我把控制權(quán)交給我的上級(jí),我需要使用的時(shí)候再向他要。這個(gè)時(shí)候,接口的作用不言而喻,A繼承了Phone接口,B也繼承了,假定我們一開(kāi)始就使用Phone接口去創(chuàng)建不同的A,B對(duì)象,那么是不是可以有效的切換AB對(duì)象呢?

      依賴(lài)注入


      依賴(lài)注入體現(xiàn)的是一個(gè)IOC(控制反轉(zhuǎn)),它非常的簡(jiǎn)單,我們之前的Man類(lèi)代碼中使用的是正轉(zhuǎn)的方式,也就是我要一個(gè)對(duì)象,那么我就創(chuàng)建一個(gè)?,F(xiàn)在我們使用依賴(lài)注入就是將我們對(duì)這個(gè)對(duì)象的控制權(quán)交給上一級(jí)接口,也就成為了這種,我想要一個(gè)對(duì)象,我就向上級(jí)發(fā)出請(qǐng)求,上級(jí)就給我創(chuàng)建了一個(gè)對(duì)象。我們通常使用構(gòu)造函數(shù)注入的方式進(jìn)行依賴(lài)的注入。

      上文的代碼就會(huì)變成
      class Man { private readonly IPhone _phone; public Man(IPhone phone) { _phone
      = phone; } }
      假設(shè)這個(gè)時(shí)候你需要將手機(jī)換成B品牌,那么只需要再注入的地方傳入B品牌的對(duì)象即可了。

      容器

      但是現(xiàn)在又出現(xiàn)了一個(gè)新的問(wèn)題,假設(shè)說(shuō)這個(gè)類(lèi)有100個(gè)使用該接口的依賴(lài),如果,我們是不是要在100個(gè)地方做這樣的事情?
      控制是反轉(zhuǎn)了,依賴(lài)的創(chuàng)建也移交到了外部?,F(xiàn)在的問(wèn)題是依賴(lài)太多,我們需要一個(gè)地方統(tǒng)一管理系統(tǒng)中所有的依賴(lài),這個(gè)時(shí)候,我們就使用容器進(jìn)行集中的管理

      容器負(fù)責(zé)兩件事情:

      * 綁定服務(wù)與實(shí)例之間的關(guān)系
      * 獲取實(shí)例,并對(duì)實(shí)例進(jìn)行管理(創(chuàng)建與銷(xiāo)毀)
      使用

      說(shuō)了那么多,我們?nèi)绾卧?NET Core中使用我們的依賴(lài)注入呢?這里我們針對(duì)的是所有的.NET Core的應(yīng)用,在.NET
      Core中依賴(lài)注入的核心分為兩個(gè)組件:位于Microsoft.Extensions.DependencyInjection命名空間下的IServiceCollection和
      IServiceProvider。

      其中

      * IServiceCollection 負(fù)責(zé)注冊(cè)
      * IServiceProvider 負(fù)責(zé)提供實(shí)例
      在默認(rèn)的容器ServiceCollection中有三個(gè)方法

      * .AddTransient<I,C>()
      * .AddSingleton<I,C>()
      * .AddScoped<I,C>()
      這里就不得不提一下我們依賴(lài)注入的三種生命周期了

      * Singleton指的是單例模式,也就是說(shuō),在整個(gè)程序運(yùn)轉(zhuǎn)期間只會(huì)生成一次
      * Transient指每一次GetService都會(huì)創(chuàng)建一個(gè)新的實(shí)例
      * Scope指在同一個(gè)Scope內(nèi)只初始化一個(gè)實(shí)例 ,可以理解為( 每一個(gè)request級(jí)別只創(chuàng)建一個(gè)實(shí)例,同一個(gè)http request會(huì)在一個(gè)
      scope內(nèi))
      我們可以嘗試使用控制臺(tái)項(xiàng)目來(lái)模擬依賴(lài)注入的原理,也就是說(shuō)我們直接從容器獲取我們對(duì)象實(shí)例,并且我們使用Guid進(jìn)行唯一性的標(biāo)記。
      //創(chuàng)建三個(gè)代表不同生命周期的接口 interface IPhoneScope { Guid Guid { get; } } interface
      IPhoneSingleton { Guid Guid { get; } } interface IPhoneTransient { Guid Guid {
      get; } } //實(shí)現(xiàn)的類(lèi) class PhoneService:IPhoneScope,IPhoneSingleton,IPhoneTransient
      { public PhoneService() { this._guid = Guid.NewGuid(); } public
      PhoneService(Guid guid) { this._guid = guid; } private Guid _guid; public Guid
      Guid => this._guid; }
      然后,在我們的主函數(shù)中
      namespace DI_AND_IOC { class Program { static void Main(string[] args) {
      //注入服務(wù) var services = new ServiceCollection() .AddScoped<IPhoneScope,
      PhoneService>() .AddTransient<IPhoneTransient, PhoneService>()
      .AddSingleton<IPhoneSingleton, PhoneService>(); //構(gòu)造服務(wù) var provider =
      services.BuildServiceProvider(); using (var scope = provider.CreateScope()) {
      var p = scope.ServiceProvider; var scopeobj1 = p.GetService<IPhoneScope>(); var
      transient1 = p.GetService<IPhoneTransient>(); var singleton1 =
      p.GetService<IPhoneSingleton>(); var scopeobj2 = p.GetService<IPhoneScope>();
      var transient2 = p.GetService<IPhoneTransient>(); var singleton2 =
      p.GetService<IPhoneSingleton>(); Console.WriteLine( $"scope1:
      {scopeobj1.Guid},\n" + $"transient1: {transient1.Guid}, \n" + $"singleton1:
      {singleton1.Guid}\n"); Console.WriteLine($"scope2: {scopeobj2.Guid}, \n" +
      $"transient2: {transient2.Guid},\n" + $"singleton2: {singleton2.Guid}\n"); }
      //創(chuàng)建不同的scope using (var scope = provider.CreateScope()) { var p =
      scope.ServiceProvider; var scopeobj3 = p.GetService<IPhoneScope>(); var
      transient3 = p.GetService<IPhoneTransient>(); var singleton3 =
      p.GetService<IPhoneSingleton>(); Console.WriteLine($"scope3: {scopeobj3.Guid},
      \n" + $"transient3: {transient3.Guid},\n" + $"singleton3: {singleton3.Guid}");
      } } } }
      你應(yīng)該會(huì)得到類(lèi)似以下的數(shù)據(jù)
      scope1: 096d38e5-0c7b-4e50-9c79-241fb18a56ed, transient1:
      289ebd11-8159-4f22-b53e-ed738a317313, singleton1:
      b453b7f5-3594-4b66-99c8-a72763abaa83 scope2:
      096d38e5-0c7b-4e50-9c79-241fb18a56ed, transient2:
      212ad420-e54c-4dd6-9214-abe91aacdd9c, singleton2:
      b453b7f5-3594-4b66-99c8-a72763abaa83 scope3:
      688b6ffd-a8c1-47f4-a20a-872c2285d67c, transient3:
      3d09997d-fffb-43d1-9e53-ccf9771c819d, singleton3:
      b453b7f5-3594-4b66-99c8-a72763abaa83
      可以發(fā)現(xiàn),singleton對(duì)象是不會(huì)發(fā)生改變的,而scope對(duì)象在創(chuàng)建新的scope之后就發(fā)生了改變,而transient對(duì)象每一次請(qǐng)求都在發(fā)生改變。

      需要注意的是,在控制臺(tái)項(xiàng)目使用容器服務(wù)需要引入 *** Microsoft.Extensions.DependencyInjection ***
      程序集,你可以在引入中導(dǎo)入該dll

      通過(guò)對(duì)注入服務(wù)的生命周期管控,在一些ASP.NET
      Core項(xiàng)目中,有些類(lèi)(服務(wù))有可能跨越了多個(gè)Action或者Controller,那么我們正確的使用生命周期,我們可以盡可能的節(jié)省內(nèi)存,即能減少實(shí)例初始化的消耗。

      在ASP.NET Core中的使用

      在ASP.NET
      Core中,我們使用依賴(lài)注入非常的簡(jiǎn)單,在StartUp類(lèi)中的ConfigureServices方法中已經(jīng)為我們構(gòu)建好了容器,我們只需要做類(lèi)似于這樣的操作
      services.AddScoped<IPhoneScope, PhoneService>();
      services.AddDbContext<DbContext>(); services.AddMVC();
      如果你需要在控制器中注入服務(wù),官方的推薦方案是使用構(gòu)造函數(shù)注入
      public IPhoneScope _ips; public Controller(IPhoneScope ips) { _ips = ips; }
      特別的,你如果使用MVC的Razor頁(yè)面進(jìn)行注入的話(huà),那么輸入以下指令
      @inject IPhoneScope ips
      如果我的文章幫助了您,請(qǐng)您在github.NETCoreGuide項(xiàng)目幫我點(diǎn)一個(gè)star,在博客園中點(diǎn)一個(gè)關(guān)注和推薦。

      Github <https://github.com/StevenEco/.NetCoreGuide>

      BiliBili主頁(yè) <https://space.bilibili.com/33311288>

      WarrenRyan'sBlog <https://blog.tity.xyz>

      博客園 <https://cnblogs.com/warrenryan>

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          草草影院www色欧美极 | 快艹我| 国产精品一区在线 | 国产精品久久久久久久久潘金莲 | www.secaobi | 特级毛片www | 国产免费无码成人A片在线观看 | 天天操天天日天天干 | 五月婷婷六月天 | 天天干天天日天天干天天日 |