.Net?WebApi中實(shí)現(xiàn)自動依賴注入的三種方法(最新推薦)
前言
該文僅供學(xué)習(xí)參考,如有問題請指正。
依賴關(guān)系注入 (DI) ,是一種軟件設(shè)計(jì)模式,這是一種在類及其依賴項(xiàng)之間實(shí)現(xiàn)控制反轉(zhuǎn) (IoC) 的技術(shù)。 .NET 中的依賴關(guān)系注入是框架的內(nèi)置部分,與配置、日志記錄和選項(xiàng)模式一樣。
生命周期
依賴注入有以下三種生命周期
- 瞬時 (Transient): 每次從服務(wù)容器進(jìn)行請求時創(chuàng)建的,請求結(jié)束后銷毀, 這種生存期適合輕量級、 無狀態(tài)的服務(wù)。
- 作用域(Scoped):在指定的范圍內(nèi),第一次請求時會創(chuàng)建一個實(shí)例,重復(fù)請求時,會返回同一個實(shí)例,在處理請求的應(yīng)用中,請求結(jié)束時會釋放有作用域的服務(wù)。使用 Entity Framework Core 時,默認(rèn)情況下 AddDbContext 擴(kuò)展方法使用范圍內(nèi)生存期來注冊 DbContext 類型。
- 單例(Singleton):單例生命周期是最長的生命周期,整個應(yīng)用程序只會創(chuàng)建一個服務(wù)實(shí)例。這種生命周期適用于那些需要在整個應(yīng)用程序中共享狀態(tài)的服務(wù),例如配置(Configuration)類、緩存(Cache)類等。
用反射實(shí)現(xiàn)自動依賴注入
定義三種生命周期的接口類
/// <summary> /// 注入標(biāo)記,Scoped作用域,每次請求時創(chuàng)建一次 /// </summary> public interface IScopedDependency { } /// <summary> /// 注入標(biāo)記,生命周期Singleton,服務(wù)第一次請求時創(chuàng)建,后續(xù)請求都使用相同的實(shí)例 /// </summary> public interface ISingletonDependency { } /// <summary> /// 注入標(biāo)記,生命周期Transient,每次請求時被創(chuàng)建,適合輕量級服務(wù) /// </summary> public interface ITransientDependency { } }
通過GetReferencedAssemblies實(shí)現(xiàn)
GetReferencedAssemblies該方法只能獲取當(dāng)前程序集所引用的外部程序集,不能獲取模式分離/間接引用的程序集
http://www.dbjr.com.cn/program/317858ubf.htm參考地址
/// <summary> /// 動態(tài)注冊所有服務(wù) /// 約定:Interfaces(注入接口), IScopedDependency(生命周期),可以有泛型接口,其它不能再繼承。 /// 注意只能注入直接引用的,間接引用的不行 /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceCollection AddDynamicinjectionService(this IServiceCollection services) { //當(dāng)前程序集 var entryAssembly = Assembly.GetEntryAssembly(); //獲取當(dāng)前程序集所引用的外部程序集,不能獲取模式分離/間接引用的程序集 var types = entryAssembly!.GetReferencedAssemblies() .Select(Assembly.Load)//裝載 .Concat(new List<Assembly>() { entryAssembly })//與本程序集合并 .SelectMany(x => x.GetTypes())//獲取所有類 .Where(x => !x.IsAbstract && x.IsClass)//排除抽象類 .Distinct(); //獲取所有繼承服務(wù)標(biāo)記的生命周期實(shí)現(xiàn)類 var busTypes = types.Where(x => x.GetInterfaces().Any(t => t == typeof(ITransientDependency) || t == typeof(IScopedDependency) || t == typeof(ISingletonDependency)); foreach (var busType in busTypes) { //過濾泛型接口 var busInterface = busType.GetInterfaces() .Where(t => t != typeof(ITransientDependency) && t != typeof(IScopedDependency) && t != typeof(ISingletonDependency) && !t.IsGenericType) .FirstOrDefault(); if (busInterface == null) continue; if (typeof(ITransientDependency).IsAssignableFrom(busType)) services.AddTransient(busInterface, busType); if (typeof(IScopedDependency).IsAssignableFrom(busType)) services.AddScoped(busInterface, busType); if (typeof(ISingletonDependency).IsAssignableFrom(busType)) services.AddSingleton(busInterface, busType); } return services; }
在Program.cs 中添加該服務(wù)
builder.Services.AddDynamicinjectionService();
加載程序集路徑實(shí)現(xiàn)
只自動注入該程序集路徑下的服務(wù),并且需要約定文件名稱
/// <summary> /// 把系統(tǒng)所有Business添加到ServiceCollection /// 加載程序集路徑動態(tài)注入 /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceCollection AddBusService(this IServiceCollection services) { string rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var busAssembly = Assembly.LoadFrom(Path.Combine(rootPath, "WenYan.Service.Business.dll")); var busTypes = busAssembly.GetTypes().Where(w => w.Name.EndsWith("Business")).ToList(); foreach (var busType in busTypes) { var busInterface = busType.GetInterfaces().Where(w => w.Name.EndsWith("Business")).FirstOrDefault(); if (busInterface == null) continue; if (typeof(ITransientDependency).IsAssignableFrom(busType)) services.AddTransient(busInterface, busType); if (typeof(IScopedDependency).IsAssignableFrom(busType)) services.AddScoped(busInterface, busType); if (typeof(ISingletonDependency).IsAssignableFrom(busType)) services.AddSingleton(busInterface, busType); } return services; }
通過依賴注入拓展庫:Scrutor,使用非常簡單,主要通過 FromAssemblyOf<> 掃描程序集和 AddClasses(o) 進(jìn)行篩選注冊
https://github.com/khellang/Scrutor 相關(guān)詳細(xì)文檔
services.Scan(scan => scan // 掃描特定類型所在的程序集,這里是 ITransientService 所在的程序集 .FromAssemblyOf<ITransientService>() // .AddClasses 在上面獲取到的程序集中掃描所有公開、非抽象類型 // 之后可以通過委托進(jìn)行類型篩選,例如下面只掃描實(shí)現(xiàn) ITransientService 的類型 .AddClasses(classes => classes.AssignableTo<ITransientService>()) // 將上面的類型作為它實(shí)現(xiàn)的所有接口進(jìn)行注冊 // 如果類型實(shí)現(xiàn)了 N 個接口,那么就會有三個獨(dú)立的注冊 .AsImplementedInterfaces() // 最后指定注冊的生存期,如瞬時,作用域,還是單例 .WithTransientLifetime() // 重復(fù)上面操作,比如這里掃描 IScopedService 所在的程序集 .AddClasses(classes => classes.AssignableTo<IScopedService>()) // 這里和上面不一樣的是,這里指定只實(shí)現(xiàn)特定的幾口,也就是只注冊一次 .As<IScopedService>() // 指定注冊的生存期 .WithScopedLifetime() // 也支持泛型注冊,單個泛型參數(shù) .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>))) .AsImplementedInterfaces() // 多個泛型參數(shù) .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))
參考鏈接
https://www.cnblogs.com/SaoJian/p/17462782.html
https://www.cnblogs.com/qianxingmu/p/13363193.html
https://furion.net/docs/dependency-injection
https://juejin.cn/post/7211158239135383611
到此這篇關(guān)于.Net WebApi中實(shí)現(xiàn)自動依賴注入的三種方法的文章就介紹到這了,更多相關(guān).Net WebApi中實(shí)現(xiàn)自動依賴注入的三種方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Grid或者DataTable中數(shù)據(jù)導(dǎo)出為Excel原來這么簡單
以前一直認(rèn)為,將Grid 或者DataTable中的數(shù)據(jù)導(dǎo)出到Excel功能實(shí)現(xiàn)會非常復(fù)雜,可能會想用什么類庫什么的或者實(shí)在太難就用csv算了,沒想到真的很簡單,需要了解的朋友可以參考下2012-12-12.NET醫(yī)院公眾號系統(tǒng)線程CPU雙高問題分析
這篇文章主要介紹了.NET醫(yī)院公眾號系統(tǒng) 線程CPU雙高分析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04Visual Studio 2017如何用正則修改部分內(nèi)容詳解
這篇文章主要給大家介紹了關(guān)于Visual Studio 2017如何用正則修改部分內(nèi)容的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05