DotNetCore依賴註入實現批量註入

来源:https://www.cnblogs.com/singleordefault/archive/2019/04/09/10677298.html
-Advertisement-
Play Games

文章轉載自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice 一、依賴註入 通過依賴註入,可以實現介面與實現類的松耦合。Asp.Net Core底層設計支持依賴註入。系統中存在的內置服務(Mvc、DbContext等 ...


文章轉載自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice

一、依賴註入

       通過依賴註入,可以實現介面與實現類的松耦合。Asp.Net Core底層設計支持依賴註入。系統中存在的內置服務(Mvc、DbContext等等)的依賴註入和自定義服務的依賴註入。其中內置服務的依賴註入,可以直接調用IServiceCollection的擴展方法(AddMvc()、AddDbContext())。

二、.Net Core底層所實現的依賴註入功能

在使用.Net Core底層所實現的依賴註入功能之前呢,需要先理解依賴註入對象的三種生命周期:

1、Transent(瞬時)生命周期在他們每次請求的時候被創建,這一生命周期適合輕量級和無狀態的服務。並且在一次請求中,如果存在多次獲取這個實例,那這些實例也是不同的。

2、Scoped(範圍)生命周期在每次請求的時候被創建,在一次請求中,如果存在多次獲取這個實例,那麼返回的也是同一個實例。

3、Singleton(單例)生命周期在它們第一次被請求的時候使用的時候創建,並且只創建一次,後續都是使用的同一個對象。

本實例使用.Net Core內置的依賴註入功能的步驟如下:

1、使用vs2017或者vs2019創建一個.Net Core WebApi項目

2、創建ISay介面,其中定義一個Say方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface ISay
    {
        string Say();
    }
}

3、創建ISay的實現類ChinseSay

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public class ChinseSay : ISay
    {
        public string Say()
        {
            Console.WriteLine("我說中國話");
            return "我說中國話";
        }
    }
}

 

4、在Startup中的ConfigureServices方法中註冊ChineseSay服務。

services.AddTransient<ISay, ChinseSay>();

 

5、模板控制器中使用依賴註入的對象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace IocPrictic.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private ISay _ISay;
        public ValuesController(ISay isay)
        {
            this._ISay = isay;
        }
        // GET api/values
        [HttpGet]
        public ActionResult<string> Get()
        {
            string sayResult= this._ISay.Say();
            return sayResult;
        }
    }
}

 

三、利用反射實現批量的依賴註入

如果需要註入的對象有多個呢?可能是幾十個也可能是幾百個,如果全是認為的進行註入的話,這是一個非常麻煩的事情。因此這裡引入了反射來實現批量註入的功能。

實現步驟(思想/演算法/...)如下:

1、定義一個需要依賴註入的標記介面(INeedInject),這個介面裡面什麼也沒有,僅僅標記一個介面需要進行依賴註入。

2、定義三個生命周期介面,這個三個介面裡面什麼也沒有(ITransentInject、IScopeInject、ISingletonInject),僅僅作為一個類型,在利用反射的時候讓其選擇對應的生命周期註入方式。

3、定義一個不需要依賴註入的標記介面(INoNeedInject),這個介面是在我們需要更換介面實現類的時候,在舊的實現類上實現這個介面,讓反射程式跳過這個實現類,去註入新的類。

4、生命周期介面繼承需要依賴註入的標記介面(INeedInject)。

5、需要依賴註入的介面繼承三種生命周期介面中的其中一種。

6、實現類實現需要依賴註入的介面。

7、利用反射更具標記介面(INeedInject)篩選出那些介面需要進行依賴註入。

8、利用反射找到這個需要進行依賴註入介面的唯一實現類。

9、根據介面定義的註入類型,選擇合適的生命周期類型去實現註入。

10、調用依賴註入的對象

(1)、INeedInject

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface INeedInject
    {
    }
}

 

(2)、三種生命周期介面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface ITransentInject:INeedInject
    {
    }
}

***********************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface IScopeInject:INeedInject
    {
    }
}

 

***********************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface ISingleTonInject:INeedInject
    {
    }
}


(3)、不需要依賴註入的標記介面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface INoNeedInject
    {
    }
}

(4)、定義需要依賴註入的介面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface ISay:ITransentInject
    {
        string Say();
    }
}

 

***********************************************

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public interface IEat:ITransentInject
    {
        string Eat();
    }
}

(5)、定義實現類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public class ChinseEat : IEat
    {
        public string Eat()
        {
            Console.WriteLine("我吃中國餐");
            return "我吃中國餐";
        }
    }
}


***********************************************

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IocPrictic
{
    public class ChinseSay : ISay
    {
        private IEat _IEat;
        public ChinseSay(IEat ieat)
        {
            this._IEat = ieat;
        }
        public string Say()
        {
            string eatResult=_IEat.Eat();
            Console.WriteLine("我說中國話");
            return $"我說中國話,{eatResult}";
        }
    }
}

(6)、利用反射實現依賴註入(核心)

在Startup中定義如下方法:

 

/// <summary>
        /// 註冊指定程式集中的服務
        /// </summary>
        /// <param name="assemblyNames">程式集名的字典</param>
        /// <param name="services">IServiceCollection類型的對象</param>
        public void BatchInjectService(IDictionary<string,string> assemblyNames,IServiceCollection services)
        {
            Type iNeedInject = typeof(INeedInject);
            Type iTransentInject = typeof(ITransentInject);
            Type iScopeInject = typeof(IScopeInject);
            Type iSingletonInject = typeof(ISingleTonInject);
            Type iNoNeedInject = typeof(INoNeedInject);//當介面切換實現類時,在舊的實現類上實現這個介面就ok
            foreach (var assemblyItem in assemblyNames)
            {
                string assemblyInterName = assemblyItem.Key;
                string assemblyObjName = assemblyItem.Key;
                Type[] interTypes = Assembly.Load(assemblyInterName).GetTypes().Where(t =>t.IsInterface && iNeedInject.IsAssignableFrom(t) && t!=iNeedInject && t!=iTransentInject && t!=iScopeInject && t!= iSingletonInject).ToArray();
                foreach (Type interType in interTypes)
                {
                    Type objType= Assembly.Load(assemblyObjName).GetTypes().Where(t =>t.IsClass && interType.IsAssignableFrom(t) && !iNoNeedInject.IsAssignableFrom(t)).SingleOrDefault();
                    if (objType == null)
                    {
                        throw new Exception($"********************當前介面={interType.Name}沒有找到對應的實現類********************");
                    }
                    IList<Type> inJectTypeList = objType.GetInterfaces().Where(i => i == iTransentInject || i == iScopeInject || i == iSingletonInject).ToList();
                    if (inJectTypeList.Count != 1)
                    {
                        throw new Exception($"********************當前介面={interType.Name}沒有找到合適的生命周期類型********************");
                    }
                    Type inJectType = inJectTypeList.Single();
                    string inJectTypeName = inJectType.Name;
                    switch (inJectTypeName)
                    {
                        case "ITransentInject": services.AddTransient(interType, objType); break;
                        case "IScopeInject": services.AddScoped(interType, objType); break;
                        case "ISingleTonInject": services.AddSingleton(interType, objType); break;
                        default: throw new Exception($"********************當前接={interType.Name}沒有指定註入實例的生命周期********************");break;
                    }  
                }
            }
        }

***********************************************

在Startup的ConfigureServices方法中調用批量依賴註入的方法:

//獲取當前程式集名

string currentAssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
IDictionary<string, string> assemblyNames = new Dictionary<string, string>();
assemblyNames.Add(currentAssemblyName, currentAssemblyName);
//批量註入指定程式集中服務
BatchInjectService(assemblyNames, services);

 

(7)、在模板控制器中調用調用依賴註入的對象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace IocPrictic.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private ISay _ISay;
        public ValuesController(ISay isay)
        {
            this._ISay = isay;
        }
        // GET api/values
        [HttpGet]
        public ActionResult<string> Get()
        {
            string sayResult= this._ISay.Say();
            return sayResult;
        }
    }
}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文鏈接:https://www.entityframeworktutorial.net/code-first/maxlength-minlength-dataannotations-attribute-in-code-first.aspx MaxLength特性指定了屬性的值所允許的最大值,然後在 ...
  • 最近在學WebSocket,服務端需要監聽多個WebSocket客戶端發送的消息。 開始的解決方法是每個WebSocket客戶端都添加一個線程進行監聽,代碼如下: /// <summary> /// 監聽埠 創建WebSocket /// </summary> /// <param name="h ...
  • 備註:本人使用開發工具:VS2017,.NET Core 2.2,其中VS2017原本自帶2.1,我單獨從官網下載了2.2的程式集安裝包,但是沒有下配套的運行環境,運行項目時出了一個問題。 以下是我在發佈Core項目後部署到IIS後運行時遇到的一些問題: 1-發佈設置: 在發佈過程中,項目一直還原n ...
  • [CommandMethod("CBline")] //對稱畫線 public void CBline() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor edit = doc.Editor; Databa ...
  • 主要代碼: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using GrxCAD.Runtime;using GrxCAD ...
  • 基於浩辰CAD2019 需求: 開發線轉圓簡單命令。命令過程:1) 請選擇圖中直線(要求支持一次選多個):2) 彈出對話框,輸入圓的圖層名和半徑3) 點對話框中確定按鈕,結束命令。命令執行效果:所選每條直線的起點和終點處,自動生成兩個圓;同時,所有直線自動整體平移MOVE一個向量AcGeVector ...
  • 在 UWP 中,如果要進行 OAuth 授權,那很大概率是會用上 WebAuthenticationBroker 這個類的,例如微博授權這種。 在一般情況下來說,WebAuthenticationBroker 是足夠用的了,但是,如果你是碰上 Github 授權的話,那麼就會碰到這樣的情況: 蹦出一 ...
  • 功能:在桌面上創建一個帶有指定數字的圖標。 效果圖: 生成的ICO圖標 代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...