我们前两章学了如何使用ASP.net Core的类,2021世界安防博览会(下称“安博会”)在广州琶洲会展中心闭幕。21世纪经济报道记者注意到,本章我们继续学依赖服务注入的概念,现场展示了不少智慧城市治理领域的“黑科技”。科讯飞的AI虚拟主播,这个也就是我们常说的DI,不仅能够说一口流利的普通话、合肥话以及英语、德语、法语等多国语言, 还有另外一个词我们也经常提及,还能及时预警各类电信网络诈骗的作案手法和防范技巧;佳都科技发布的智慧社区,那就是 - 控制反转。很多同学在学到这两个概念的时候,通过数据、人工智能技术实现了对社区感知,可能经常会有些莫名其妙,构建了一个重点人员管控、案件侦查打击、领导决策分析、民生服务的基层治理新格。数据、人工智能究竟有何赋能智慧城市治理?智慧安防行业接下来又有哪些发展趋势?21世纪经济报道记者为此采访了佳都科技智慧城市行业系统总监刘弘胤。他表示,IoC和DI到底有什么联系和区别?这两个概念有人说是一回事,如今智慧城市已成为未来城市的必然发展趋势,实际上这个理解是错特错,安防作为智慧城市的其中一个场景,个人认为正确的理解应该是:IoC是目的,发展潜力不容小觑。同时,而且DI是实现IoC的手段。所谓的控制反转实际的目的是将流程委托给应用程序的框架,在“新基建”拉动市场需求的过程中,也就是将控制交给框架,然后由框架使用一定的技术,方便用户以这些技术或者接口扩展该框架的功能,实际上也就是将某些场景的流程控制功能模块化交由框架来实现,留出接口来方便用户控制和扩展,这就是IoC的设计目的,而DI就是实现这个目的的技术之一,也是目前用得最多的技术。
我们先来总结一下提供的DI功能:
必须使用接口或者是基类来抽象化类之间的依赖关系。
将依赖关系注册到由提供的服务容器中,这个在中是以接口的实现类来表示的,依赖关系一般注册到实现了接口的容器类中,一般是在应用启动的时候完成注册的,一旦完成注册后,使用方法来创建服务容器。
在中通过构造函数来完成依赖注入,由框架来负责创建应用需要的实例,并在不需要它的时候回收它。
需要注意的是在的DI属于中,服务(Service), 只要是指:
向其他对象提供服务的对象,而且被服务的对象都需要通过依赖而注入的这些类。
服务这个概念不是仅仅为了准备的,虽然多数的时候它被用在应用中。
另外对于.Net框架,它有提供默认的几个服务,后面的章节我们会来了解和学它。
框架提供服务
框架提供了一些内置的服务,这些是由在创建和配置的时候默认就已经初始化好了,在客户的应用方法方法之前就已经注入到系统中了。如下是列表:
DI的生命周期
服务注册到DI系统中去之后,每个服务都是有生命周期的,生命周期代表框架什么时候创建这个服务,什么时候销毁它。
目前支持三种:
Transient
Scoped
Singleton
Transient
在注册服务的时候选择范围,表示每次需要这个服务都会创建一个新的,例如在一个方法里多次向服务请求某个服务,那么就会多次创建这个服务的实例,使用方法对服务进行注册。
Scoped
在web应用中,范围表示在一次客户端请求,都属于在一个的范围内置。在非应用中,使用变量作用域来衡量生命周期比较合适。使用方法进行注册。
Singleton
代表从应用开始启动,到应用shutdown, 这个时间范围都只有一个实例服务,称为范围。使用方法进行注册。
服务注册的方法:
我们前面学过了通过什么方法来注册服务,同时我们还以用下表来表示注册的方法:
构造函数注入
构造函数注入需要注意:
用于注入的构造函数除了需要从容器中注入的参数之外,也可以有其他的参数,但是要求这个参数必须有默认值。
用于注入的构造函数必须是public的。
应用类中最好只有一个合适的构造函数。
注意
请注意如下的几点提示:
不要在Singleton范围内调用scoped或者transient范围的服务, 无论是直接调用还是间接调用。
可以从scoped或者tranisent范围里调用singleton。
可以从scoped或者tranisent范围里调用scoped。
服务清理
注册到服务容器中,并且由服务容器根据范围进行管理的,不用者来担心清理,由容器来负责清理的行为, 建议服务实现接口。
需要注意的是,在注册服务的时候,参考上述的表,如果服务不是由容器实例的,者需要自己清理,例如Singleton。
自动依赖服务最佳实践
、、以及基于Task的异步编程,在依赖注入的服务中不被支持,因为C#不支持异步构造函数,可以在同步方法中取得了注入的服务,然后在异步方法中使用该服务,这没有问题,只是服务本身不支持异步编程。
避免直接在服务中存储数据或者更改配置。
避免在服务中使用静态方法。
保持创建服务的工厂方法快而且简单。
避免使用类似来取得服务,而是通过DI
启用范围验证。
ASP.net Core Startup类中依赖注入
需要注意的是在类中,只有构造函数和方法中可以注入需要依赖的服务, 同时构造函数只能注入如下几种类型:
IWebHostEniroment
IHostEnviroment
IConfiguration
但是任何其他已经注册了的服务都可以注入到方法
HttpContext.RequestService
在ASP.net core也可以通过 取得scoped 范围的服务,但是官方推荐还是尽量使用构造函数的参数来取得服务。
ASP.net Core MVC 中的Controller如何取得注册在容器里的服务
在ASP.net Core里有两种形式可以从DI容器中取得服务:
从构造函数中取得。
使用属性[FromService] 放入参数列表中,可以无需使用构造函数就可以取得服务了。
关于第二种,看一下这个例子:
publicIActionResultAbout([FromServices]IDateTimedateTime)
{
returnContent($"Current server time:");
}
从控制器中存取配置
不建议直接将对象注入到中去,而是采取模式。我们先看如下的例子,后面再用一节来学什么是
先创建一个类表示配置选项:
publicclassSleWebSettings
{
publicstringTitle {get;set; }
publicintUpdates {get;set; }
}
添加这个配置类到服务里。
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddSingleton();
services.Configure(Configuration);
services.AddControllersWithViews();
}
配置应用从json格式里读取配置
publicclassProgram
{
publicstaticvoidMain(string[]args)
{
CreateHostBuilder(args).Build().Run();
}
publicstaticIHostBuilderCreateHostBuilder(string[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config)=>
{
config.AddJsonFile("slewebsettings.json",
optional:false,
reloadOnChange:true);
})
.ConfigureWebHostDefaults(webBuilder=>
{
webBuilder.UseStartup();
});
}
从控制器里存取配置
这里例子里我们通过从依赖容器中取得配置。
publicclassSettingsController:Controller
{
privatereadonlySleWebSettings_settings;
publicSettingsController(IOptionssettingsOptions)
{
_settings=settingsOptions.Value;
}
publicIActionResultIndex()
{
ViewData["Title"]=_settings.Title;
ViewData["Updates"]=_settings.Updates;
returnView();
}
}
我们下一节来学, 依赖注入总结到这里就好了。
往期文章目录:
ASP.net Core基础
AzureDeveloper,一个分享和学Azure技术的好去处,欢迎关注
免责声明:文中图片均来源于网络,如有版权问题请联系我们进行删除!
标签: