欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.Net?WebApi中實(shí)現(xiàn)自動依賴注入的三種方法(最新推薦)

 更新時間:2024年03月16日 09:08:24   作者:無顏組  
依賴關(guān)系注入 (DI) ,是一種軟件設(shè)計(jì)模式,這是一種在類及其依賴項(xiàng)之間實(shí)現(xiàn)控制反轉(zhuǎn) (IoC)?的技術(shù), .NET 中的依賴關(guān)系注入是框架的內(nèi)置部分,與配置、日志記錄和選項(xiàng)模式一樣,這篇文章主要介紹了.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)文章

最新評論