如何在.net6webapi中使用自動(dòng)依賴(lài)注入
IOC/DI
IOC(Inversion of Control)控制反轉(zhuǎn):控制反正是一種設(shè)計(jì)思想,旨在將程序中的控制權(quán)從程序員轉(zhuǎn)移到了容器中。容器負(fù)責(zé)管理對(duì)象之間的依賴(lài)關(guān)系,使得對(duì)象不再直接依賴(lài)于其他對(duì)象,而是通過(guò)依賴(lài)注入的方式來(lái)獲取所需的資源。
DI(Dependency Injection)依賴(lài)注入:他是IOC的具體實(shí)現(xiàn)方式之一,使用最為廣泛,DI通過(guò)在運(yùn)行時(shí)動(dòng)態(tài)地將某個(gè)依賴(lài)關(guān)系抽象為獨(dú)立的組件,提交到容器之中,需要使用時(shí)再由容器注入,提升組件重用的頻率,為系統(tǒng)搭建一個(gè)靈活,可擴(kuò)展的平臺(tái)。
IOC/DI是一種設(shè)計(jì)模式,用于解耦組件之間的依賴(lài)關(guān)系。在傳統(tǒng)的編程模式中,組件之間的依賴(lài)關(guān)系是硬編碼在代碼中的,這樣會(huì)導(dǎo)致代碼的耦合度很高,難以維護(hù)和發(fā)展。而IOC/DI模式則是通過(guò)將組件之間的依賴(lài)關(guān)系交給容器來(lái)管理,組件不再直接依賴(lài)其他組件,而是通過(guò)容器來(lái)獲取所依賴(lài)的對(duì)象。這樣可以使組件之間的依賴(lài)關(guān)系更加靈活,容器可以根據(jù)需要?jiǎng)討B(tài)地創(chuàng)建和管理組件,從而實(shí)現(xiàn)更好的可維護(hù)性和可擴(kuò)展性。
如何在.net6webapi中使用依賴(lài)注入?
首先我們定義一個(gè)服務(wù)接口及對(duì)應(yīng)的實(shí)現(xiàn)
public interface ITestServices
{
int return123();
} public class TestServices : ITestServices
{
public int return123()
{
return 123;
}
}然后我們?cè)赑rogram.cs注入服務(wù)實(shí)現(xiàn)
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddTransient<ITestServices, TestServices>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();值得注意的是依賴(lài)注入有三種生命周期
- 作用域(Scoped):在應(yīng)用程序啟動(dòng)時(shí)創(chuàng)建,并在應(yīng)用程序關(guān)閉時(shí)銷(xiāo)毀。這種類(lèi)型的服務(wù)實(shí)例會(huì)被容器管理,但是只會(huì)被當(dāng)前請(qǐng)求使用。當(dāng)請(qǐng)求結(jié)束時(shí),該服務(wù)實(shí)例會(huì)被銷(xiāo)毀。
- 單例(Singleton):在應(yīng)用程序啟動(dòng)時(shí)創(chuàng)建,并在整個(gè)應(yīng)用程序運(yùn)行期間保持不變。這種類(lèi)型的服務(wù)實(shí)例會(huì)被容器管理,并且可以被多個(gè)請(qǐng)求共享。
- 瞬時(shí)(Transient):在應(yīng)用程序啟動(dòng)時(shí)創(chuàng)建,并在應(yīng)用程序關(guān)閉時(shí)銷(xiāo)毀。這種類(lèi)型的服務(wù)實(shí)例不會(huì)被容器管理,也不會(huì)被其他服務(wù)引用。
最后在需要使用的控制器中構(gòu)造函數(shù)注入就可以使用了
[Route("[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly ITestServices _testServices;
public TestController(ITestServices testServices)
{
_testServices= testServices;
}
[HttpGet]
public int Get123() => _testServices.return123();
}
怎么實(shí)現(xiàn)自動(dòng)注入?
依賴(lài)注入好歸好,就是每個(gè)服務(wù)都得在Program.cs注入服務(wù)實(shí)現(xiàn),一但服務(wù)多起來(lái),麻煩不說(shuō),Program.cs中的代碼更是會(huì)變得凌亂不堪,可能會(huì)有小伙伴說(shuō),可以開(kāi)一個(gè)擴(kuò)展函數(shù)單獨(dú)做注入,但私以為,既然有一種方法可以一勞永逸,何樂(lè)而不為呢?
其實(shí)現(xiàn)便是利用.net的高級(jí)特性之一,反射
首先我們定義三個(gè)生命周期接口,其對(duì)應(yīng)依賴(lài)注入的三種生命周期
//瞬時(shí)注入服務(wù)接口
public interface ITransient
{ }
//作用域注入服務(wù)接口
public interface IScoped
{ }
//單例注入服務(wù)接口
public interface ISingleton
{ }然后我們定義自動(dòng)注入的擴(kuò)展方法,其為核心實(shí)現(xiàn)
public static IServiceCollection RegisterAllServices(this IServiceCollection services)
{
//獲取當(dāng)前程序集
var entryAssembly = Assembly.GetEntryAssembly();
//獲取所有類(lèi)型
//!. null包容運(yùn)算符,當(dāng)你明確知道表達(dá)式的值不為null 使用!.(即null包容運(yùn)算符)可以告知編譯器這是預(yù)期行為,不應(yīng)發(fā)出警告
//例: entryAssembly!.GetReferencedAssemblies() 正常
//entryAssembly.GetReferencedAssemblies() 編譯器判斷entryAssembly有可能為null,變量下方出現(xiàn)綠色波浪線(xiàn)警告
var types = entryAssembly!.GetReferencedAssemblies()//獲取當(dāng)前程序集所引用的外部程序集
.Select(Assembly.Load)//裝載
.Concat(new List<Assembly>() { entryAssembly })//與本程序集合并
.SelectMany(x => x.GetTypes())//獲取所有類(lèi)
.Distinct();//排重
//三種生命周期分別注冊(cè)
Register<ITransient>(types, services.AddTransient, services.AddTransient);
Register<IScoped>(types, services.AddScoped, services.AddScoped);
Register<ISingleton>(types, services.AddSingleton, services.AddSingleton);
return services;
}
/// <summary>
/// 根據(jù)服務(wù)標(biāo)記的生命周期interface,不同生命周期注冊(cè)到容器里面
/// </summary>
/// <typeparam name="TLifetime">注冊(cè)的生命周期</typeparam>
/// <param name="types">集合類(lèi)型</param>
/// <param name="register">委托:成對(duì)注冊(cè)</param>
/// <param name="registerDirectly">委托:直接注冊(cè)服務(wù)實(shí)現(xiàn)</param>
private static void Register<TLifetime>(IEnumerable<Type> types, Func<Type, Type, IServiceCollection> register, Func<Type, IServiceCollection> registerDirectly)
{
//找到所有標(biāo)記了Tlifetime生命周期接口的實(shí)現(xiàn)類(lèi)
var tImplements = types.Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Any(tinterface => tinterface == typeof(TLifetime)));
//遍歷,挨個(gè)以其他所有接口為key,當(dāng)前實(shí)現(xiàn)為value注冊(cè)到容器中
foreach (var t in tImplements)
{
//獲取除生命周期接口外的所有其他接口
var interfaces = t.GetInterfaces().Where(x => x != typeof(TLifetime));
if (interfaces.Any())
{
foreach (var i in interfaces)
{
register(i, t);
}
}
//有時(shí)需要直接注入實(shí)現(xiàn)類(lèi)本身
registerDirectly(t);
}
}其核心邏輯便是通過(guò)反射掃描程序集,當(dāng)掃描到實(shí)現(xiàn)了我們定義的生命周期接口時(shí),為其實(shí)現(xiàn)對(duì)應(yīng)的生命周期注入。
注冊(cè)這個(gè)服務(wù)
builder.Services.RegisterAllServices();
然后我們就可以通過(guò)繼承生命周期接口來(lái)實(shí)現(xiàn)自動(dòng)服務(wù)注入
public interface ITestServices
{
int return123();
} public class TestServices : ITestServices, ITransient
{
public int return123()
{
return 123;
}
}接下來(lái)無(wú)需在Program.cs注入服務(wù)實(shí)現(xiàn)

調(diào)用成功。
到此這篇關(guān)于如何在.net6webapi中實(shí)現(xiàn)自動(dòng)依賴(lài)注入的文章就介紹到這了,更多相關(guān).net6webapi自動(dòng)依賴(lài)注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net 生成曲線(xiàn)圖實(shí)現(xiàn)代碼
這里是從Dataset里的數(shù)據(jù)生成曲線(xiàn)圖.2009-02-02
CZGL.ProcessMetrics處理監(jiān)控?cái)?shù)據(jù)的三種方式介紹
這篇文章介紹了CZGL.ProcessMetrics處理監(jiān)控?cái)?shù)據(jù)的三種方式,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
asp.net與Discuz!NT整合集成實(shí)例教程
由于項(xiàng)目需要一個(gè)論壇,本來(lái)有CS的,在.net下很出名的國(guó)外開(kāi)源論壇。但為了適應(yīng)國(guó)內(nèi)的風(fēng)氣,最后選用在國(guó)內(nèi)如日中天的Discuz!NT。將Discuz與asp.net開(kāi)發(fā)的網(wǎng)站整合,有很多人已經(jīng)完成了。2009-11-11
c# Random快速連續(xù)產(chǎn)生相同隨機(jī)數(shù)的解決方案
在寫(xiě)數(shù)獨(dú)基類(lèi)的時(shí)候?yàn)榱水a(chǎn)生隨機(jī)數(shù)的時(shí)候遇到奇怪的問(wèn)題2009-03-03
ASP.NET中利用存儲(chǔ)過(guò)程實(shí)現(xiàn)模糊查詢(xún)
ASP.NET中利用存儲(chǔ)過(guò)程實(shí)現(xiàn)模糊查詢(xún)...2006-09-09
.Net Core WebApi部署到Windows服務(wù)器上的步驟
這篇文章主要介紹了.Net Core WebApi部署到Windows服務(wù)器上的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
.NET?如何使用?OpenTelemetry?metrics?監(jiān)控應(yīng)用程序指標(biāo)
這篇文章主要介紹了.NET?使用?OpenTelemetry?metrics?監(jiān)控應(yīng)用程序指標(biāo),通過(guò)代碼演示了如何通過(guò) OpenTelemetry 把 Metrics 的數(shù)據(jù)發(fā)送到 Prometheus 里進(jìn)行查詢(xún)與展示,然后又演示了自定義相關(guān)指標(biāo)來(lái)滿(mǎn)足業(yè)務(wù)數(shù)據(jù)指標(biāo)的監(jiān)控,需要的朋友可以參考下2024-06-06
VS2019下opencv4.1.2配置圖文教程(永久配置)
這篇文章主要介紹了VS2019下opencv4.1.2配置圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11
ASP.NET2.0中用Gridview控件操作數(shù)據(jù)的代碼
在ASP.NET 2.0中,加入了許多新的功能和控件,相比asp.net 1.0/1.1,在各方面都有了很大的提高2012-10-10
ASP.NET中Webservice安全 實(shí)現(xiàn)訪(fǎng)問(wèn)權(quán)限控制
本文主要講解ASP.NET中的Webservice的安全設(shè)置兩種方法,一種基于soapheader,一種基于SoapExtensionAttribute,需要的朋友可以參考下。2016-05-05

