.NET基于類名約定的自動依賴注入完整指南

🚀 .NET基于類名約定的自動依賴注入完整指南

基于類名約定的自動依賴注入可大幅減少手動注冊服務的工作量,本文將通過清晰的結構、美觀的排版和豐富的示例,幫助你快速掌握這一實用技術。

🌈 核心特性概覽

特性說明
類名約定自動識別以 Service 結尾的類(不區分大小寫)
接口優先匹配優先注冊到 I{ClassName} 形式的接口(如 UserServiceIUserService
多生命周期支持支持 Transient/Scoped/Singleton 三種生命周期
靈活掃描控制可指定任意程序集或默認掃描調用程序集
無接口自注冊自動注冊未實現接口的類為自身類型

📦 完整代碼實現(含所有重載)

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Reflection;/// <summary>
/// 依賴注入擴展方法集合(基于類名約定)
/// </summary>
public static class ServiceCollectionExtensions
{/// <summary>/// 自動注冊以"Service"結尾的類(默認Transient生命周期)/// </summary>public static IServiceCollection AutoRegisterServices(this IServiceCollection services,Assembly assembly = null){assembly ??= Assembly.GetCallingAssembly();// 掃描規則:公共類、非抽象、非泛型、類名以Service結尾var serviceTypes = assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.IsPublic &&!t.ContainsGenericParameters &&t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase)).ToArray();// 注冊服務到容器foreach (var implType in serviceTypes){var interfaces = implType.GetInterfaces();if (interfaces.Any()){// 匹配I{ClassName}接口(如UserService→IUserService)var matchingInterface = interfaces.FirstOrDefault(i => i.Name == "I" + implType.Name);if (matchingInterface != null){services.AddTransient(matchingInterface, implType);}else{// 注冊到所有實現的接口foreach (var @interface in interfaces){services.AddTransient(@interface, implType);}}}else{// 無接口時注冊自身services.AddTransient(implType);}}return services;}/// <summary>/// 自動注冊以"Service"結尾的類(支持自定義生命周期)/// </summary>public static IServiceCollection AutoRegisterServices(this IServiceCollection services,ServiceLifetime lifetime,Assembly assembly = null){assembly ??= Assembly.GetCallingAssembly();var serviceTypes = GetServiceTypes(assembly);foreach (var implType in serviceTypes){var interfaces = implType.GetInterfaces();var descriptor = CreateServiceDescriptor(implType, interfaces, lifetime);services.Add(descriptor);}return services;}// 輔助方法:獲取服務類型(提取公共邏輯)private static Type[] GetServiceTypes(Assembly assembly) =>assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.IsPublic &&!t.ContainsGenericParameters &&t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase)).ToArray();// 輔助方法:創建服務描述符(提取公共邏輯)private static ServiceDescriptor CreateServiceDescriptor(Type implType, Type[] interfaces, ServiceLifetime lifetime){if (interfaces.Any()){var matchingInterface = interfaces.FirstOrDefault(i => i.Name == "I" + implType.Name);if (matchingInterface != null){return new ServiceDescriptor(matchingInterface, implType, lifetime);}// 返回第一個接口(避免注冊多個描述符)return new ServiceDescriptor(interfaces[0], implType, lifetime);}return new ServiceDescriptor(implType, implType, lifetime);}
}

🚀 使用示例(清晰排版)

1. 在ASP.NET Core中注冊(Program.cs

var builder = WebApplication.CreateBuilder(args);// 方式1:默認Transient(掃描調用程序集)
builder.Services.AutoRegisterServices();// 方式2:指定Scoped生命周期
builder.Services.AutoRegisterServices(ServiceLifetime.Scoped);// 方式3:掃描指定程序集(如業務層)
var businessAssembly = Assembly.Load("MyBusinessLayer");
builder.Services.AutoRegisterServices(ServiceLifetime.Singleton, businessAssembly);var app = builder.Build();

2. 服務類示例(符合約定的實現)

// ? 示例1:接口匹配型服務
public interface IUserService { string GetInfo(); }
public class UserService : IUserService 
{public string GetInfo() => "User Service Running";
}// ? 示例2:多接口實現服務
public interface IAuthService { void Login(); }
public interface ILogService { void WriteLog(string msg); }
public class AuthService : IAuthService, ILogService 
{public void Login() { /* 登錄邏輯 */ }public void WriteLog(string msg) { /* 日志邏輯 */ }
}// ? 示例3:無接口自注冊服務
public class DataService 
{public void ProcessData() { /* 數據處理 */ }
}// ? 示例4:不符合約定的類(不會被注冊)
public class ServiceHelper { }        // 類名不以Service結尾
public abstract class BaseService { } // 抽象類

🔧 擴展優化方案(帶emoji標記)

1. 🌐 基于類名的生命周期自動識別

private static ServiceLifetime GetLifetimeFromName(string className)
{if (className.Contains("Singleton", StringComparison.OrdinalIgnoreCase))return ServiceLifetime.Singleton;if (className.Contains("Scoped", StringComparison.OrdinalIgnoreCase))return ServiceLifetime.Scoped;return ServiceLifetime.Transient;
}

2. 📌 特性標記增強控制

[AttributeUsage(AttributeTargets.Class)]
public class AutoRegisterAttribute : Attribute 
{public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Transient;public bool IsEnabled { get; set; } = true;
}

3. ? 緩存掃描結果提升性能

private static readonly object LockObj = new();
private static Type[] _cachedServiceTypes;private static Type[] GetCachedServiceTypes(Assembly assembly)
{if (_cachedServiceTypes == null){lock (LockObj){_cachedServiceTypes = assembly.GetTypes().Where(t => /* 掃描規則 */).ToArray();}}return _cachedServiceTypes;
}

📝 最佳實踐指南

  1. 📦 混合注冊策略

    • 核心服務(如DbContext)手動注冊:
      services.AddDbContext<AppDbContext>(options => {...});
    • 業務服務自動注冊:
      builder.Services.AutoRegisterServices();
  2. 🔍 精準掃描范圍

    // 僅掃描當前程序集中的服務
    builder.Services.AutoRegisterServices(typeof(UserService).Assembly);
    
  3. ? 單元測試驗證

    [Fact]
    public void Should_Resolve_Service_By_Convention()
    {var services = new ServiceCollection();services.AutoRegisterServices(typeof(IAuthService).Assembly);var provider = services.BuildServiceProvider();var service = provider.GetService<IAuthService>();Assert.NotNull(service);
    }
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87868.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87868.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87868.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis各數據結構的詳細使用和使用場景

Redis各數據結構的詳細使用 大家好&#xff01;今天我們來聊聊Redis這個強大的內存數據庫。就像我們生活中的工具箱一樣&#xff0c;Redis提供了多種"工具"&#xff08;數據結構&#xff09;來幫助我們解決不同的問題。有些工具像螺絲刀&#xff08;字符串&#xff…

MSYS2 環境下 Python 開發配置(結合 PyCharm)使用筆記

【筆記】MSYS2 的 MinGW64 環境中正確安裝 Python 相關環境管理工具 &#xff08;Poetry、Virtualenv、Pipenv 和 UV&#xff09;-CSDN博客 MSYS2 環境配置與 Python 項目依賴管理筆記_msys更新python-CSDN博客 【技術筆記】MSYS2 指定 Python 版本安裝方案_pacman -u 安裝指定…

Python爬蟲實戰:研究Splinter相關技術

1. 引言 1.1 研究背景與意義 隨著 Web 2.0 技術的發展,現代網頁越來越多地采用 JavaScript 動態生成內容。傳統爬蟲通過直接請求 HTML 頁面的方式,無法獲取這些動態渲染的內容,導致爬取數據不完整。據統計,全球前 1000 名網站中,超過 70% 的頁面包含動態加載內容 。Spli…

大氣商務工作匯報總結PPT模版分享

藍色商務工作總結PPT模版&#xff0c;莫蘭迪工作總結PPT模版&#xff0c;年中工作匯報PPT模版&#xff0c;簡約工作匯報PPT模版&#xff0c;上半年工作總結PPT模版&#xff0c;極簡工作匯報PPT模版&#xff0c;歐美簡約PPT模版&#xff0c;大氣商務通用PPT模版&#xff0c;團隊…

5G modem開發

鏈接文章&#xff1a;https://zhuanlan.zhihu.com/p/709130546 OpenHarmony RIL架構 鏈接文章&#xff1a;https://blog.csdn.net/weixin_42571280/article/details/148566029 在移動通信設備中&#xff0c;無線接口層&#xff08;Radio Interface Layer&#xff0c;簡稱RIL&…

Gartner《AI-Driven Methods for Cost-Efficiency》學習心得

一、背景介紹 在當前經濟形勢下,企業面臨著成本上升與收入增長放緩的雙重壓力。Gartner 的這份報告指出,大多數企業對 AI 的投資主要集中在提升用戶生產力方面,但短期內投資回報率有限。鑒于經濟的不確定性以及成本壓力,尤其是生成式 AI(GenAI)技術,若應用于財務效率和…

人臉識別技術是自動化還是智能化?

人臉識別技術兼具自動化與智能化的雙重特性。它通過自動采集圖像、預處理圖像、提取特征以及進行識別比對等操作&#xff0c;實現了高效且無需人工干預的識別流程&#xff0c;展現出強大的自動化能力。同時&#xff0c;它還具備自適應學習能力&#xff0c;能夠根據新的數據和場…

樹結構的實際應用之堆排序

樹結構的實際應用之堆排序 基本介紹 堆排序是利用堆這種數據結構設計而成的一種排序算法&#xff0c;堆排序是一種選擇排序&#xff0c;它的最壞&#xff0c;最好&#xff0c;平均時間復雜度為O(logn)&#xff0c;它也是不穩定排序。堆是具有以下性質的完全二叉樹&#xff1a;…

用OBS Studio錄制WAV音頻,玩轉語音克隆和文本轉語音!

言簡意賅的講解OBS Studio解決的痛點 隨著AI技術的快速發展&#xff0c;語音克隆與文本生成語音技術越來越受歡迎。無論你想要制作個人虛擬主播&#xff0c;還是給自媒體視頻配音&#xff0c;擁有高質量的原始音頻都是關鍵。本文詳細教你使用免費且功能強大的軟件——OBS Stud…

LangChain-5-agent

概述 Agent 是一種能夠基于接收到的輸入&#xff0c;利用自身的決策邏輯和可用的工具&#xff0c;動態地規劃并執行一系列操作&#xff0c;以達成特定任務的程序或系統。它在與外界交互過程中&#xff0c;會根據實時情況靈活調整策略&#xff0c;而不是按照固定的預設流程執行…

操作系統進程與線程核心知識全覽

本博客&#xff0c;根據王道所學。以下為第二章節知識點&#xff1a; 進程的概念、組成、狀態與其轉換、進程間通信、信號&#xff1b; 單/多線程模型、線程管理、調度時機的切換、調度的目標、調度算法、多處理機調度&#xff1b; 同步與互斥、進程互斥的軟硬件實現方法、信號…

C++中類型轉換操作符知識介紹

文章目錄 **一、類型轉換操作符的語法與定義****二、工作原理****三、示例&#xff1a;基本類型轉換****四、示例&#xff1a;轉換為自定義類型****五、與構造函數的對比****六、注意事項****七、應用場景****八、與 C 其他類型轉換的關系****九、總結** 在C中&#xff0c;類型…

2048小游戲C++板來啦!

個人主頁&#xff1a;PingdiGuo_guo 收錄專欄&#xff1a;C干貨專欄 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我們來學習如何用C編寫一個2048小游戲。 文章目錄 1.2048的規則 2.步驟實現 2.1: 初始化游戲界面 2.1.1知識點 2.1.2: 創建游戲界面 2.2: 隨機…

TensorFlow深度學習實戰——Transformer變體模型

TensorFlow深度學習實戰——Transformer變體模型 0. 前言1. BERT2. GPT-23. GPT-34. Reformer5. BigBird6. Transformer-XL7. XLNet8. RoBERTa9. ALBERT10. StructBERT11. T5 和 MUM12. ELECTRA13. DeBERTa14. 進化 Transformer 和 MEENA15. LaMDA16. Switch Transformer17. RE…

還原自動駕駛的“前世今生”:用 Python 實現數據記錄與回放系統

還原自動駕駛的“前世今生”:用 Python 實現數據記錄與回放系統 你有沒有想過這樣一個場景: 一輛自動駕駛測試車,在街頭拐了個彎,卻突然急剎。測試員一臉懵,研發團隊問:“數據記錄了嗎?” 他攤攤手:“系統當時沒掛上錄制……” 對不起,重測吧。 這不是段子,而是我在…

access和excel用vba進行輔助辦公軟件開發

1、access用vba創建子窗口child查詢 出現這個報錯的時候&#xff0c;一般是用vba通過ado.connection連接&#xff0c;沒有綁定數據源造成的&#xff1a; 先綁定再使用 Me.Child2.SourceObject "表.資產管理" 連接數據源 Me.Child2.Form.RecordSource strSql …

Nginx+tomcat集群

Nginxtomcat集群 一、Nginx 簡介 1.1 定義 Nginx 是一個高性能的 HTTP 和反向代理 web 服務器&#xff0c;同時支持 IMAP/POP3/SMTP 服務。由俄羅斯工程師伊戈爾?賽索耶夫開發&#xff0c;于 2004 年首次公開發布&#xff0c;基于 BSD-like 協議&#xff0c;代碼開源且免費…

RPC - 客戶端注冊和發現模塊

registryMethod 函數詳解&#xff1a; 函數目的 registryMethod 是 Provider 類的核心方法&#xff0c;用于向服務注冊中心注冊服務。注冊成功后&#xff0c;服務注冊中心會更新內部的服務映射表&#xff0c;建立服務名稱到提供者地址的映射關系。 執行流程示例 場景: 多米…

leetcode332.重新安排行程:優先隊列與DFS實現歐拉路徑的行程規劃

一、題目深度解析與行程規劃本質 題目描述 給定一個機票的字符串二維數組 tickets&#xff0c;每個元素是 [from, to] 的形式&#xff0c;表示從 from 到 to 的機票。要求找出從 JFK 出發的行程&#xff0c;且必須使用所有機票&#xff0c;若存在多種可能的行程&#xff0c;返…

1.21SQLCipher 簡介

SQLCipher 是一個基于 SQLite 的擴展&#xff0c;提供了透明的數據庫加密功能。與普通 SQLite 不同&#xff0c;SQLCipher 在數據寫入磁盤前自動加密&#xff0c;讀取時自動解密&#xff0c;無需開發者手動處理加密邏輯。這使得它非常適合移動應用、桌面應用等需要本地數據加密…