.NET 依赖注入
ASP.NET Core
支持依赖项注入(DI)软件设计模式,这是一种用于在类及其依赖项之间实现控制反转(IoC)的技术。
引用nuget包
.net core
使用了接口与实现分离的设计模式,这样的好处是第三方的 Ioc 容器只需要引用 Microsoft.Extensions.DependencyInjection.Abstractions
包,并实现其中的接口,就可以与 .net core
框架完美兼容了。
1
2
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.DependencyInjection
简单示例
声明接口及其实现类
1
2
3
4
5
6
//声明一个接口
public interface IVipService
{}
//声明IVipService接口的实现类
public class VipService : IVipService
{}
在 Startup.cs
的 ConfigureServices
方法中将接口实现添加到 Ioc
容器
1
2
3
4
5
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IVipService, VipService>();
services.AddControllers();
}
通过构造函数注入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IVipService _vipService;
public WeatherForecastController( IVipService vipService) //在构造函数中注入IVipService接口
{
_vipService = vipService;
}
[HttpGet]
public string Get( )
{
return _vipService.GetHashCode().ToString();
}
}
通过方法注入:
1
2
3
4
5
6
7
8
9
10
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public string Get([FromServices]IVipService vipService) // 在方法入参中使用[FromServices]特性注入IVipService接口
{
return vipService.GetHashCode().ToString();
}
}
这样我们就完成了一个依赖注入的简单示例,当有请求路由到 WeatherForecastController
控制器时,依赖注入框架会自动将Ioc容器中的实现类创建好注入到 WeatherForecastController
中,这样 WeatherForecastController
也就不在依赖于 IVipService
的具体实现类,如果需要更换 IVipService
的实现,那么只需要修改 services.AddScoped<IVipService, VipService>()
; 这一段代码就可以了。
生命周期
.net core
的依赖注入框架支持创建三种不同生命周期的服务。
1
2
3
4
5
6
7
8
9
public enum ServiceLifetime
{
// 单例模式
Singleton = 0,
// 作用域模式
Scoped = 1,
// 瞬时模式
Transient = 2
}
- Singleton :单例模式,在整个应用程序的生命周期内,每次调用都使用同一个实例。
- Scoped :作用域模式,在同一个作用域内,每次调用都使用同一个实例。
- Transient:瞬时模式,每次调用都会创建一个新的实例。
三种生命周期,使用下面三种不同的方法注入
1
2
3
services.AddSingleton<IVipService, VipService>();
services.AddScoped<IVipService, VipService>();
services.AddTransient<IVipService, VipService>();
实现了 IDisposable
接口并且由容器创建的实例由容器主动释放,其他的实例生命周期结束后由 GC
释放。
泛型模板注入
1
services.AddSingleton(typeof(IVipService<>),typeof(VipService<>));
工厂注入(用以处理一些特殊的情况)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//一个接口 两个实现类
public interface IVipService
{
}
public class ErpVipService : IVipService
{
}
public class WxVipService : IVipService
{
}
//将工厂包装一层
public class VipServiceFactory
{
private readonly Func<int, IVipService> _func;
public VipServiceFactory(Func<int, IVipService> func)
{
_func = func;
}
public IVipService GetInstence(int type)
{
return _func(type);
}
}
//注入扩展类
public static class VipServiceExtensions
{
public static IServiceCollection AddVipService(this IServiceCollection services)
{
services.AddScoped<ErpVipService>();
services.AddScoped<WxVipService>();
//通过工厂方式根据类型条件决定创建哪个实现类 //该方法在所线程情况下,可能会遇到serviceProvider已被释放的问题。
services.AddScoped(serviceProvider =>
{
Func<int, IVipService> func = type =>
{
if (type == 0) return (IVipService)serviceProvider.GetService<ErpVipService>();
else
return (IVipService)serviceProvider.GetService<WxVipService>();
};
return func;
});
services.AddScoped<VipServiceFactory>();
return services;
}
}
在 ConfigureServices
中注入
1
2
3
4
5
public void ConfigureServices(IServiceCollection services)
{
services.AddVipService();
services.AddControllers();
}
控制器中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly VipServiceFactory _vipServiceFactory;
//将工厂类注入到构造函数
public WeatherForecastController(VipServiceFactory vipServiceFactory)
{
_vipServiceFactory = vipServiceFactory;
}
[HttpGet]
public string Get( )
{
return _vipServiceFactory.GetInstence(0).GetHashCode().ToString();
}
}
开源框架推荐
- Scrutor: Kristian Hellang 大神写的一个基于
Microsoft.Extensions.DependencyInjection
的一个扩展库,主要是为了简化我们对DI的操作。 - Autofac: .NET 领域最为流行的 IoC 框架之一,功能多,性能好,易学习。
参考资源
本文由作者按照 CC BY 4.0 进行授权