ASP.NET Core支持依赖项注入(DI)软件设计模式,这是一种用于在类及其依赖项之间实现控制反转(IoC)的技术。
引用nuget包
.net core使用了接口与实现分离的设计模式,这样的好处是第三方的Ioc容器只需要引用Microsoft.Extensions.DependencyInjection.Abstractions包,并实现其中的接口,就可以与.net core框架完美兼容了。
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.DependencyInjection
简单示例
声明接口及其实现类
//声明一个接口 public interface IVipService {} //声明IVipService接口的实现类 public class VipService : IVipService {}
在Startup.cs的ConfigureServices方法中将接口实现添加到Ioc容器
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IVipService, VipService>();
services.AddControllers();
}
通过构造函数注入:
[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(); } }
通过方法注入:
[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的依赖注入框架支持创建三种不同生命周期的服务。
public enum ServiceLifetime { // 单例模式 Singleton = 0, // 作用域模式 Scoped = 1, // 瞬时模式 Transient = 2 }
Singleton :单例模式,在整个应用程序的生命周期内,每次调用都使用同一个实例。
Scoped :作用域模式,在同一个作用域内,每次调用都使用同一个实例。
Transient:瞬时模式,每次调用都会创建一个新的实例。
三种生命周期,使用下面三种不同的方法注入 services.AddSingleton<IVipService, VipService>(); services.AddScoped<IVipService, VipService>(); services.AddTransient<IVipService, VipService>();
实现了IDisposable接口并且由容器创建的实例由容器主动释放,其他的实例生命周期结束后由GC释放。
泛型模板注入
services.AddSingleton(typeof(IVipService<>),typeof(VipService<>));
工厂注入(用以处理一些特殊的情况)
//一个接口 两个实现类 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>(); //通过工厂方式根据类型条件决定创建哪个实现类 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中注入
public void ConfigureServices(IServiceCollection services) { services.AddVipService(); services.AddControllers(); }
控制器中使用
[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(); } }
手写Ioc容器
自己手撸的一个简单Ioc容器实现,只是用以了解Ioc的内部实现原理,不喜勿喷。
地址:https://github.com/Jasonbourne723/eShop/blob/main/src/Tests/dotnet.Console.Test/Program.cs
开源框架推荐
Scrutor: Kristian Hellang 大神写的一个基于Microsoft.Extensions.DependencyInjection的一个扩展库,主要是为了简化我们对DI的操作。
Autofac: .NET领域最为流行的IoC框架之一,功能多,性能好,易学习。
官方文档
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1