DotNetCore跨平台~一起聊聊Microsoft.Extensions.DependencyInjection
写这篇文章的心情:激动
Microsoft.Extensions.DependencyInjection在github上同样是开源的,它在dotnetcore里被广泛的使用,比起之前的autofac,unity来说,它可以说是个包裹,或者叫适配器,它自己提供了默认的DI实现,同时也支持第三方的IOC容器,在这段时间里使用了它,就想,这东西为什么被在dotnetcore里大放异彩?为什么会全程使用它?从程序的开始到程序启动起来,你可以发现它无处不在,在框架里是这样,在业务层同时也是这样。
聊聊Microsoft.Extensions.DependencyInjection知识点包括
- 它的开源地址
- IServiceCollection和IApplicationBuilder
- 自定义模块用它
- 在Startup.ConfigureServices中注册自定义模块
- 在Startup.Configure中使用它,进行默认模块的初始化
- 在任意对象的构造方法中使用它
一步一步的揭秘
一 它的开源地址
https://github.com/aspnet/DependencyInjection
可以看看它的README.md,就知道它是个大包裹,类似于大叔LindAgile里的Container,完全可以扩展支持其它第三方的IOC容器,这就像大叔经常说的那句话一样,在IT江湖中,英雄总是所风略同……

二 dotnetcore整个框架在用它
在你的dotnetcore应用程序里,你会发现在Startup类中有很多像services.AddMvc()这样的方法,这实质是像应用程序中注册一个组件,这里的MVC是一个统一的组件,它不依赖于windows,不依赖于dotnet,整个dotnetcore里把很多组件都解耦了,这样在维护和nuget包升级时都更灵活,自己有问题就优化自己,而不影响其它模块。(越说越像微服务的宗旨)。
IServiceCollection主要用来注册服务,就是某个接口和某种实现的对应关系,这种注册是我们在Startup.ConfigureServices方法里完成的,如下面的AddLind()这个方法,它完成了对Lind模块的注册,在方法内部可以注册本模块的其它服务。
/// <summary>
/// 添加Lind框架和它们依赖子模块
/// </summary>
/// <param name="services"></param>
/// <param name="setupAction"></param>
/// <returns></returns>
public static LindBuilder AddLind(
this IServiceCollection services,
Action<LindOptions> setupAction)
{
if (setupAction == null) throw new ArgumentNullException(nameof(setupAction));
services.Configure(setupAction);
var options = new LindOptions();
//注册框架所依赖的基础模块
//options.Extensions.Add();
//注册外部模块
setupAction(options);
foreach (var serviceExtension in options.Extensions)
serviceExtension.AddServices(services);
services.AddSingleton(options);
return new LindBuilder(services);
}
IApplicationBuilder是指对应该程序的启动,或者理解为初始化,当上面的服务注册完成后就执行它了,我们一般在Startup.Configure去激活它,它的目的比较单纯,就是对模块进行初始化,如果没什么特殊的功能,这个代码可以是空的,下面Builder中初始化了日志组件。
/// <summary>
/// 在应用程序中开启-Lind框架
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder" /> instance this method extends.</param>
/// <returns>The <see cref="IApplicationBuilder" /> instance this method extends.</returns>
public static IApplicationBuilder UseLind(this IApplicationBuilder app)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
var provider = app.ApplicationServices; //注册Lind框架所需要的底层服务
LoggerFactory.SetLogger((ILogger)provider.GetService(typeof(ILogger)));
return app;
}
三 自定义模块用它
如果希望定义自己的功能模块实现与dotnetcore框架的结合可以自定义Options和OptionsExtensions,前者主要实现的是服务列表的注册,而后台主要是对现有模块提供注册的入口,下面的代码主要实现了一个EF仓储模块的注册过程。
模块所需的模型
public class RepositoryOptions
{
public string ConnString { get; set; }
}
注册服务列表
/// <summary>
/// 注册有关-EF仓储的服务列表
/// </summary>
public class EFOptionsExtension : ILindOptionsExtension
{
private readonly Action<RepositoryOptions> _configure; public EFOptionsExtension(Action<RepositoryOptions> configure)
{
_configure = configure;
}
public void AddServices(IServiceCollection services)
{
services.AddSingleton(typeof(IRepository), typeof(EFRepository));
var mysqlOptions = new RepositoryOptions();
_configure(mysqlOptions);
}
}
在外部使用这个模块,就是在Startup中注册它
public static class RepositoryOptionsExtensions
{
public static LindOptions UseEF(this LindOptions options, Action<RepositoryOptions> configure)
{
options.RegisterExtension(new EFOptionsExtension(configure)); return options;
}
}
四 在Startup.ConfigureServices中注册自定义模块
上面的代码主要是自定义一个模块,而在startup中使用它,就像下面的代码,十分简洁,当前有些配置信息可以到在基于环境变量的json文件里!
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddLind(x =>
{
x.UseEF(o =>
{
o.ConnString = "localhost:1433";
});
x.UseDapper(o =>
{
o.ConnString = "localhost:3306";
});
});
}
五 在Startup.Configure中使用它,进行默认模块的初始化
上面的代码实现了对模块下一些服务进行注册,然后下面代码主要是进行一些初始化的工作。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc();
app.UseLind();
}
六 在任意对象的构造方法中使用它
当我们把服务注册后,可以在任意类型的构造方法中使用它,而不是只能在控制器中使用,这一点dotnetcore DI做的确实不错,给它100个赞!
这种注册
public class ApiLoggerOptionsExtension : IPilipaOptionsExtension
{
Action<ApiLoggerConfig> _config;
public ApiLoggerOptionsExtension(Action<ApiLoggerConfig> config)
{
_config = config;
}
public void AddServices(IServiceCollection services)
{
ApiLoggerConfig apiLoggerConfig = new ApiLoggerConfig();
_config(apiLoggerConfig);//装饰
services.AddSingleton(apiLoggerConfig);//注册对象里的属性,在对象的构造方法被注入
services.AddSingleton(typeof(ILogger), typeof(ApiLogger));//注册对象,在使用对象的类的构造方法被注入
}
}
这种使用
ApiLoggerConfig _config;
public ApiLogger(ApiLoggerConfig config)
{
_config = config;
}
对于上面的代码实现了在OptionsExtension里进行注册,然后在任意类型中使用它,感觉这点确实灵活了不少!
今天咱们对dotnetcore DependencyInjection的分享就到这里,希望大家也尽量把模块从项目中解放出来!
感谢各位的阅读!
DotNetCore跨平台~一起聊聊Microsoft.Extensions.DependencyInjection的更多相关文章
- 解析 Microsoft.Extensions.DependencyInjection 2.x 版本实现
项目使用了 Microsoft.Extensions.DependencyInjection 2.x 版本,遇到第2次请求时非常高的内存占用情况,于是作了调查,本文对 3.0 版本仍然适用. 先说结论 ...
- 使用诊断工具观察 Microsoft.Extensions.DependencyInjection 2.x 版本的内存占用
目录 准备工作 大量接口与实现类的生成 elasticsearch+kibana+apm asp.net core 应用 请求与快照 Kibana 上的请求记录 请求耗时的分析 请求内存的分析 第2次 ...
- Microsoft.Extensions.DependencyInjection 之三:展开测试
目录 前文回顾 IServiceCallSite CallSiteFactory ServiceProviderEngine CompiledServiceProviderEngine Dynamic ...
- Microsoft.Extensions.DependencyInjection 之三:反射可以一战(附源代码)
目录 前文回顾 IServiceCallSite CallSiteFactory ServiceProviderEngine CompiledServiceProviderEngine Dynamic ...
- Microsoft.Extensions.DependencyInjection 之二:使用诊断工具观察内存占用
目录 准备工作 大量接口与实现类的生成 elasticsearch+kibana+apm asp.net core 应用 请求与快照 Kibana 上的请求记录 请求耗时的分析 请求内存的分析 第2次 ...
- Microsoft.Extensions.DependencyInjection 之一:解析实现
[TOC] 前言 项目使用了 Microsoft.Extensions.DependencyInjection 2.x 版本,遇到第2次请求时非常高的内存占用情况,于是作了调查,本文对 3.0 版本仍 ...
- 使用 Microsoft.Extensions.DependencyInjection 进行依赖注入
没有 Autofac DryIoc Grace LightInject Lamar Stashbox Unity Ninject 的日子,才是好日子~~~~~~~~~~ Using .NET Core ...
- MvvmLight + Microsoft.Extensions.DependencyInjection + WpfApp(.NetCore3.1)
git clone MvvmLight失败,破网络, 就没有直接修改源码的方式来使用了 Nuget安装MvvmLightLibsStd10 使用GalaSoft.MvvmLight.Command命名 ...
- Microsoft.Extensions.DependencyInjection中的Transient依赖注入关系,使用不当会造成内存泄漏
Microsoft.Extensions.DependencyInjection中(下面简称DI)的Transient依赖注入关系,表示每次DI获取一个全新的注入对象.但是使用Transient依赖注 ...
随机推荐
- 关于querySelector 和 document.getElementsByTagName 选中集合问题
本文解决的问题是 :运用for..of..循环时,edge浏览器报Object doesn't support property or method 'symbol.iterator'问题 以及 符号 ...
- select选择框在谷歌火狐和IE样式的不同
select选择在不同浏览器不同的显示样式, 在IE中 虽然默认和谷歌一样,但是当点击时向下 按钮消失, 解决方法如下: select { /*Chrome和Firefox里面的边框是不一样的,所以复 ...
- bootstrap 表单+按钮+对话框
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 团队作业2——需求分析&原型设计
Deadline: 2017-4-14 22:00PM,以博客发表日期为准 评分基准: 按时交 - 有分,检查的项目包括后文的三个方面 需求分析 原型设计 编码规范 晚交 - 0分 迟交两周以上 - ...
- 个人作业2————英语学习APP的案例分析
必应词典案例分析 第一部分 调研, 评测 1.下载并使用 第一次使用必应词典,安装完打开便是这样的界面,第一印象还行,界面平平无奇,比较简洁,上面分四个模块,这样一眼看去感觉功能比较单一 使用了下例句 ...
- 201521123103 《Java学习笔记》 第八周学习总结
一.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 集合部分:TreeMap实现类:对键值进行排序. Map的entrySet Set<Map.Entry&l ...
- 201521123067 《Java程序设计》第7周学习总结
201521123067 <Java程序设计>第7周学习总结 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 Q1.ArrayList代码分析 ...
- 201521123078《Java程序设计》第1周学习总结
1. 本周学习总结 简单的了解JVM,JRE,JDK,编写简单的Java程序 2. 书面作业 为什么java程序可以跨平台运行?执行java程序的步骤是什么?(请用自己的语言书写) 通过JVM虚拟机, ...
- 201521123111《Java程序设计》第10周学习总结
1. 本章学习总结 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容 线程不是程序 线程必须在程序对应的进程中运行 一个进程中可以同时执行多个线程,这些线程可以完成不同的功能. 2. 书面 ...
- 201521123073 《Java程序设计》第13周学习总结
1. 13周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jm ...