.Net WebApi中实现自动依赖注入的三种方法(最新推荐)

 更新时间:2024年03月16日 09:08:24   作者:無顏組  
依赖关系注入 (DI) ,是一种软件设计模式,这是一种在类及其依赖项之间实现控制反转 (IoC) 的技术, .NET 中的依赖关系注入是框架的内置部分,与配置、日志记录和选项模式一样,这篇文章主要介绍了.Net WebApi中实现自动依赖注入的三种方法,需要的朋友可以参考下

前言

该文仅供学习参考,如有问题请指正。

依赖关系注入 (DI) ,是一种软件设计模式,这是一种在类及其依赖项之间实现控制反转 (IoC) 的技术。 .NET 中的依赖关系注入是框架的内置部分,与配置、日志记录和选项模式一样。

生命周期

依赖注入有以下三种生命周期

  • 瞬时 (Transient): 每次从服务容器进行请求时创建的,请求结束后销毁, 这种生存期适合轻量级、 无状态的服务。
  • 作用域(Scoped):在指定的范围内,第一次请求时会创建一个实例,重复请求时,会返回同一个实例,在处理请求的应用中,请求结束时会释放有作用域的服务。使用 Entity Framework Core 时,默认情况下 AddDbContext 扩展方法使用范围内生存期来注册 DbContext 类型。
  • 单例(Singleton):单例生命周期是最长的生命周期,整个应用程序只会创建一个服务实例。这种生命周期适用于那些需要在整个应用程序中共享状态的服务,例如配置(Configuration)类、缓存(Cache)类等。

用反射实现自动依赖注入

定义三种生命周期的接口类

    /// <summary>
    /// 注入标记,Scoped作用域,每次请求时创建一次
    /// </summary>
    public interface IScopedDependency
    {
    }
    /// <summary>
    /// 注入标记,生命周期Singleton,服务第一次请求时创建,后续请求都使用相同的实例
    /// </summary>
    public interface ISingletonDependency
    {
    }
    /// <summary>
    /// 注入标记,生命周期Transient,每次请求时被创建,适合轻量级服务
    /// </summary>
    public interface ITransientDependency
    {
    }
}

通过GetReferencedAssemblies实现

GetReferencedAssemblies该方法只能获取当前程序集所引用的外部程序集,不能获取模式分离/间接引用的程序集
https://www.jb51.net/program/317858ubf.htm参考地址

/// <summary>
/// 动态注册所有服务
/// 约定:Interfaces(注入接口), IScopedDependency(生命周期),可以有泛型接口,其它不能再继承。
/// 注意只能注入直接引用的,间接引用的不行
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddDynamicinjectionService(this IServiceCollection services)
{
	//当前程序集
	var entryAssembly = Assembly.GetEntryAssembly();
	//获取当前程序集所引用的外部程序集,不能获取模式分离/间接引用的程序集
	var types = entryAssembly!.GetReferencedAssemblies()
		.Select(Assembly.Load)//装载
		.Concat(new List<Assembly>() { entryAssembly })//与本程序集合并
		.SelectMany(x => x.GetTypes())//获取所有类
		.Where(x => !x.IsAbstract && x.IsClass)//排除抽象类
		.Distinct();
	//获取所有继承服务标记的生命周期实现类
	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 中添加该服务
builder.Services.AddDynamicinjectionService();

加载程序集路径实现

只自动注入该程序集路径下的服务,并且需要约定文件名称

/// <summary>
/// 把系统所有Business添加到ServiceCollection
/// 加载程序集路径动态注入
/// </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) 进行筛选注册

https://github.com/khellang/Scrutor 相关详细文档

services.Scan(scan => scan
    // 扫描特定类型所在的程序集,这里是 ITransientService 所在的程序集
    .FromAssemblyOf<ITransientService>()
        // .AddClasses 在上面获取到的程序集中扫描所有公开、非抽象类型
        // 之后可以通过委托进行类型筛选,例如下面只扫描实现 ITransientService 的类型
        .AddClasses(classes => classes.AssignableTo<ITransientService>())
            // 将上面的类型作为它实现的所有接口进行注册
            // 如果类型实现了 N 个接口,那么就会有三个独立的注册
            .AsImplementedInterfaces()
            // 最后指定注册的生存期,如瞬时,作用域,还是单例
            .WithTransientLifetime()
        // 重复上面操作,比如这里扫描 IScopedService 所在的程序集
        .AddClasses(classes => classes.AssignableTo<IScopedService>())
            // 这里和上面不一样的是,这里指定只实现特定的几口,也就是只注册一次
            .As<IScopedService>()
            // 指定注册的生存期
            .WithScopedLifetime()
        // 也支持泛型注册,单个泛型参数
        .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))
            .AsImplementedInterfaces()
        // 多个泛型参数
        .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

到此这篇关于.Net WebApi中实现自动依赖注入的三种方法的文章就介绍到这了,更多相关.Net WebApi中实现自动依赖注入的三种方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 树莓派ASP.NET环境配置过程详解

    树莓派ASP.NET环境配置过程详解

    这篇文章主要介绍了树莓派ASP.NET环境配置,本篇文章内容是根据mono官网上查阅的配置教程所写,需要的朋友可以参考下
    2022-04-04
  • WPF使用DockPanel停靠面板布局

    WPF使用DockPanel停靠面板布局

    这篇文章介绍了WPF使用DockPanel停靠面板布局的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Grid或者DataTable中数据导出为Excel原来这么简单

    Grid或者DataTable中数据导出为Excel原来这么简单

    以前一直认为,将Grid 或者DataTable中的数据导出到Excel功能实现会非常复杂,可能会想用什么类库什么的或者实在太难就用csv算了,没想到真的很简单,需要了解的朋友可以参考下
    2012-12-12
  • .NET医院公众号系统线程CPU双高问题分析

    .NET医院公众号系统线程CPU双高问题分析

    这篇文章主要介绍了.NET医院公众号系统 线程CPU双高分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Visual Studio 2017如何用正则修改部分内容详解

    Visual Studio 2017如何用正则修改部分内容详解

    这篇文章主要给大家介绍了关于Visual Studio 2017如何用正则修改部分内容的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • 浅析MVP模式中V-P交互问题及案例分享

    浅析MVP模式中V-P交互问题及案例分享

    如果从层次关系来讲,MVP属于Presentation层的设计模式。对于一个UI模块来说,它的所有功能被分割为三个部分,分别通过Model、View和Presenter来承载。Model、View和Presenter相互协作,完成对最初数据的呈现和对用户操作的响应,它们具有各自的职责划分。
    2014-05-05
  • .Net Core中使用Grpc的方法

    .Net Core中使用Grpc的方法

    这篇文章主要介绍了.Net Core中使用Grpc的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • 浅谈ASP.NET Core的几种托管方式

    浅谈ASP.NET Core的几种托管方式

    这篇文章主要介绍了浅谈ASP.NET Core的几种托管方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • asp.net显示页面执行时间

    asp.net显示页面执行时间

    Global.asax需要添加的代码。利用我们了解当前页面的运行效率。
    2009-03-03
  • ASP.NET加密解密算法分享

    ASP.NET加密解密算法分享

    这篇文章主要分享的是ASP.NET实现的加密解密算法,非常的简单使用,有需要的小伙伴快来参考下吧。
    2015-03-03

最新评论