使用.net core 自带DI框架实现 延迟加载
在某些情况,我们希望能延迟一个依赖的初始化。如果使用的是autofac,我们可以通过注入Lazy来实现。
我们对 autofac GitHub上提供的一个例子进行进行简单改造,跑起来看看。
原Example的链接https://github.com/autofac/Examples/tree/master/src/AspNetCoreExample
微改后的代码
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly Lazy<IValuesService> _valuesService;
public ValuesController(Lazy<IValuesService> valuesService)
{
_valuesService = valuesService;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
// Kestrel模式下这里会输出false,实例尚未创建
Console.WriteLine(_valuesService.IsValueCreated);
// 调用Lazy<T>的Value属性才真正创建实例
return this._valuesService.Value.FindAll();
}
}
直到目前core2.1版本,自带的DI依旧未支持延迟加载,如果我们尝试在使用自带DI的情况下套用上述代码,会得到一个异常,例如:
An unhandled exception occurred while processing the request.
InvalidOperationException: Unable to resolve service for type 'System.Lazy`1[WebApplication9.Services.IValuesService]' while attempting to activate 'WebApplication9.Controllers.ValuesController'.
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)
如何利用core自带的DI实现呢?如果我们尝试百度,可能会搜到类似下面的答案。
services.AddTransient(typeof(Lazy<>));
那么这样的做法是否能解决我们的问题呢,为了简化演示代码。我们创建一个控制台程序并引用Microsoft.Extensions.DependencyInjection。
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddScoped<ITestService, TestService>();
services.AddTransient(typeof(Lazy<>));
var serviceProvider = services.BuildServiceProvider();
using (var scope = serviceProvider.CreateScope() )
{
var service = scope.ServiceProvider.GetService<Lazy<ITestService>>();
// 这边令人遗憾地输出了true,也就是说,这种方式的延迟注入是失败的
Console.WriteLine(service.IsValueCreated);
}
}
}
在查阅Stack Overflow的时候,我看到了这样的解决方案,感觉还是挺简单实用的,分享给大家。
原贴地址:https://stackoverflow.com/questions/44934511/does-net-core-dependency-injection-support-lazyt
public class LazyLoader<T> : Lazy<T>
{
public LazyLoader(IServiceProvider sp) : base(sp.GetRequiredService<T>)
{
}
}
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddScoped<ITestService, TestService>();
// services.AddScoped(typeof(Lazy<>), typeof(LazyLoader<>)); 也可以,区别不大
services.AddTransient(typeof(Lazy<>), typeof(LazyLoader<>));
var serviceProvider = services.BuildServiceProvider();
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<Lazy<ITestService>>();
Console.WriteLine(service.IsValueCreated); // 输出false
// 下面输出true,延迟注入的对象和正常注入的对象,本质上不会有差别
Console.WriteLine(service.Value == scope.ServiceProvider.GetService<ITestService>());
}
}
}
实现原理比较简单,在LazyLoader中注入ServiceProvider,调用父类的Value属性时会执行委托,从ServiceProvider中获取到对应得依赖实例。
使用.net core 自带DI框架实现 延迟加载的更多相关文章
- 在.net core自带DI中服务生命周期 Transient,Scoped,Singleton
只要是透过WebHost产生实例的类型,都可以在构造方法注入.所以Controller.View.Filter.Middleware或自定义的Service等都可以被注入. Transient是瞬时的 ...
- .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]
原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...
- 利用ASP.netCore自带DI(DependencyInjection)实现批量依赖注入
ASP.net Core自带DI(依赖注入),用法如下: services.AddScoped(typeof(IProductService), typeof(ProductService)); 如果 ...
- 依赖注入[4]: 创建一个简易版的DI框架[上篇]
本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章(<控制反转>.<基于IoC的设计模式>和< 依赖注入模式>)从纯理论的角度 ...
- ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)
在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...
- ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)
在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...
- 如何在ASP.NET Core应用中实现与第三方IoC/DI框架的整合?
我们知道整个ASP.NET Core建立在以ServiceCollection/ServiceProvider为核心的DI框架上,它甚至提供了扩展点使我们可以与第三方DI框架进行整合.对此比较了解的读 ...
- 依赖注入[8]: .NET Core DI框架[服务消费]
包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.当需要消费某个服务实例的时候,我们只需要指定服务类型调用IServicePr ...
- 依赖注入[7]: .NET Core DI框架[服务注册]
包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.服务注册就是创建出现相应的ServiceDescriptor对象并将其添加到 ...
随机推荐
- tree的所有节点都勾选上或者取消勾选
还有一个功能,就是让tree的所有节点都勾选上或者取消勾选,在api中找了一下有一个方法: check target 选中指定节点. 那我们只能是选中根节点后,实现全选. getRoot none 获 ...
- C6 P5.2
引用自 http://snippetinfo.net/media/117 下载源:php-5.2-x64.zip wget 源包.zip yum -y install httpd libXpm.so. ...
- JAVA中Colllection的基本功能
Collection中的add方法: 代码: public static void main(String[] args) { // TODO Auto-generated method ...
- linux shell脚本编程笔记(二): 分支结构
1.if if command then commands fi if command then commands else commands fi if command1 then command ...
- 高性能Web服务器Nginx的配置与部署研究(6)核心模块之主模块的测试常用指令
1. daemon 含义:设置是否以守护进程模式运行 语法:daemon on|off 缺省:on 示例:daemon off; 注意:生产环境(production mode)中不要使用daemon ...
- ubuntu mysql导出数据库及数据
mysqldump -u root -p mask_rcnn_realsense > /home/luo/mask_rcnn_realsense1.sql
- 3-为什么很多 对 1e9+7(100000007)取模
首先有很多题目的答案是很大的,然而出题人的本意也不是让选手写高精度或者Java,所以势必要让答案落在整型的范围内.那么怎么做到这一点呢,对一个很大的质数取模即可(自行思考为什么不是小数).那么如果您学 ...
- 手把手教你生成二维码-google.zxing
一.目标 输入网址,生成网址的二维码 二.概况 1.效果:UI丑,但功能实现了 2.项目目录 三.用到的第三方资源 1.google的扫码包zxing 2.JQuery 四.步骤(用myEclipse ...
- css中calc()的使用
calc()是css3中新出现的特性,可以用于动态计算,非常方便. 首先是兼容性 再来看看怎么使用 html{ font-size: 20px; } div{ width: calc(50% - 1p ...
- Python原始套接字编程-乾颐堂
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...