Blazor University (46)依赖注入 —— Transient 依赖

原文链接:https://blazor-university.com/dependency-injection/dependency-lifetimes-and-scopes/transient-dependencies/

Transient 依赖

Transient 依赖是最容易理解的。在构建注册为 Transient 的可注入依赖项时,依赖项容器只是充当工厂。一旦实例被创建并注入到依赖组件中,容器就不再对它感兴趣了。

警告:这仅适用于未实现 IDisposable 的实例。为避免潜在的内存泄漏,请阅读本节底部的避免内存泄漏部分。

为了说明 Transient 依赖的生命周期,我们将创建一个简单的应用程序,以便我们可以查看对象实例的创建时间。

Transient 依赖示例

源代码[1]

首先,创建一个新的 Blazor 服务器应用。然后新建一个名为 Services 的文件夹,添加如下界面。这是我们的 UI 将用来显示由依赖容器创建并注入到我们的组件中的对象的实例编号的服务。每个实例将其 InstanceNumber 设置为下一个可用的序列号。

public interface IMyTransientService
{public int InstanceNumber { get; }
}

为了实现这个接口,我们将编写一个带有静态整数字段的类,我们可以使用它来确定下一个可用的序列号。该字段将被标记为 volatile 并使用 System.Threading.Interlocked.Increment 进行更改,因此我们可以跨多个线程修改该字段,而无需进行任何线程锁定。

public sealed class MyTransientService : IMyTransientService
{public int InstanceNumber { get; }private static volatile int PreviousInstanceNumber;public MyTransientService(){InstanceNumber = System.Threading.Interlocked.Increment(ref PreviousInstanceNumber);}
}

注册我们的依赖

在服务器端应用程序中编辑 Startup.ConfigureServices 并添加以下代码:

services.AddTransient<IMyTransientService, MyTransientService>();

在 WebAssembly 应用程序中编辑 Program.Main 并在调用 builder.Build() 之前添加以下代码。

builder.Services.AddTransient<IMyTransientService, MyTransientService>();

使用 Transient 依赖

为了使用这种 Transient 依赖,我们将创建一个组件,以便我们可以在主页上显示使用组件的多个实例。该组件将简单地声明一个注入的依赖项,然后显示它的 InstanceNumber

Shared 文件夹中,创建一个名为 MyStandardComponent.razor 的新组件,并为其添加以下标记。

@inject IMyTransientService TransientService<p>Instance = @TransientService.InstanceNumber</p>

演示 Transient 生命周期

接下来,我们将编辑 Index.razor,以便我们可以通过选中或取消选中复选框来显示/隐藏该组件的实例。除非选中相关复选框,否则我们的标记不会呈现组件的实例。因为 Blazor 仅在需要时创建组件实例,所以切换复选框将在它显示时重新创建我们的组件,并允许它在不显示时被垃圾回收。

<div><input id="show-first" type="checkbox" @bind=ShowFirst /><label for="show-first">Show first</label>@if (ShowFirst){<MyStandardComponent />}
</div><div><input id="show-second" type="checkbox" @bind=ShowSecond /><label for="show-second">Show second</label>@if (ShowSecond){<MyStandardComponent />}
</div>@code
{bool ShowFirst;bool ShowSecond;
}
  • 第 19-20 行

    声明布尔字段以确定是否应创建和呈现两个组件中的每一个。

  • 第 2 行

    在复选框上使用双向绑定,因此我们可以在 falsetrue 之间切换布尔字段。

  • 第 5 行

    如果相关字段为 true,则显示 MyStandardComponent 的一个实例。

运行应用程序

当应用程序第一次运行时,两个布尔字段都将为 false,因此两个 MyStandardComponent 标记都不会被呈现。

94f0a10c9b33e18a6cbff72ea054e2b4.jpeg

当我们选中其中一个复选框时,它将双向绑定到其相关的布尔字段,将其设置为 true。然后,用户交互将导致组件的重新渲染,从而导致我们的 MyStandardComponent 实例之一被渲染 - 因此 Blazor 将创建它的一个实例并注入一个新创建的 MyTransientService,其 InstanceNumber 为 1。

下图显示了当“Show second”是第一个要选中的复选框时的预期输出。

e326bac10307cd1baf55fa4f89520413.jpeg

选中另一个复选框将再次导致重新渲染,另一个 MyStandardComponent 将被创建并使用 InstanceNumber 为 2 的依赖项进行渲染,因为注入其中的 Transient 依赖项是按需创建的。

f16983e5e0cb969b39316cfc4c0b68e5.jpeg

每当我们取消选中一个复选框时,我们的页面标记将不再呈现相关的 MyStandardComponent,因为它只是基于 @if 语句有条件地呈现。当它被取消选中并且页面重新渲染时,现有组件不再被引用并且允许被垃圾收集。

当我们选中同一个复选框时,我们的条件将得到满足,我们的页面将呈现相关的 MyStandardComponent,将创建一个新实例,将创建一个 MyTransientService 的新实例以注入其中,我们将看到一个显示 3 的组件为其 InstanceNumber

5210da35c3d89f10caa3434fc3e45c3a.jpeg

  1. 该页面在没有创建任何组件的情况下呈现。

  2. 选中第 2 个复选框,将 ShowSecond 设置为 true。

  • 页面重新渲染,第 2 个组件可见。

  • 我们组件的一个新实例被创建。

  • 我们的 transient 服务的一个新实例(实例 1)被创建并注入到组件中。

选中第 1 个复选框,将 ShowFirst 设置为 true。

  • 页面重新渲染,第  1 个组件可见。

  • 我们组件的一个新实例被创建。

  • 我们的 transient 服务的一个新实例被创建(实例 2)并注入其中。

第 1 个复选框未选中,将 ShowFirst 设置为 false。

  • 第一个组件不再呈现,因此它会被垃圾回收。

  • 再次选中第 1 个复选框,将 ShowFirst 设置为 true。

  • 页面被重新渲染。

  • 我们组件的一个新实例被创建。

  • 我们的 transient 服务(实例 3)的一个新实例被创建并注入其中。

避免内存泄漏

如果类不实现 IDisposable,则仅将其注册为 Transient 依赖项,否则,您的应用程序将泄漏内存。

默认情况下,Microsoft 依赖注入容器将简单地创建注册为 Transient 的依赖项实例,然后忘记它们。当这些实例被注入的组件被收集后,这些实例就会被垃圾收集。

从历史上看,Microsoft 依赖注入框架在 ASP.NET 应用程序中被广泛使用,其中为传入的 Web 请求创建一个容器,然后在请求结束时将其处理掉。

为了避免开发人员不得不释放任何注入的依赖项的不便,Microsoft 依赖项注入容器将在释放时自动对任何实现 IDisposable 的对象调用 Dispose

为此,每当它创建一个实现 IDisposable 的实例时,容器必须存储对所创建实例的引用,以便调用它的 Dispose 方法。这意味着当创建 Transient 依赖项时,行为会根据实例是否是一次性的而有所不同。

Transient 对象通常在它们被注入的对象符合垃圾回收条件后才符合垃圾回收条件——除非它们实现了 IDisposable,在这种情况下,注入容器还将持有对创建的瞬态 IDisposable 的引用,然后它才符合垃圾回收条件,一旦创建它的容器有资格进行垃圾回收,就进行回收。

Blazor 中的依赖注入容器一直存在,直到用户关闭浏览器中包含 Blazor 应用程序的选项卡。这意味着除了在需要时创建 Transient 依赖项的新实例外,容器还将永远保留它们——导致内存泄漏。

有一种方法可以为每个组件创建一个依赖范围(因此它会在组件被释放时被释放),这将在后面的部分中介绍。

如果您想将依赖项注册为 Transient,最好避免对完全实现 IDisposable 的类这样做。

总结

将可注入依赖项注册为 Transient 使我们的依赖项容器充当该类型实例的工厂。同一个实例不能自动注入多个消费类,每个注入的实例总是唯一的。

实现 IDisposable 的类不应注册为 Transient,除非使用拥有自己 Scope 的组件,并且您确切地知道自己在做什么(您已阅读 Scoped 依赖项部分)。

参考资料

[1]

源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/DependencyInjection/TransientLifetimes

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AM335x 添加 HUAWEI MU609 Mini PCIe Module,并用pppd 启动相关设备

kernel 的配置kernel 3.2.0make menuconfigDevice Drivers --->[*] USB support ---><*> USB Serial Converter support ---><*> USB driver for GSM and CDMA modems kernel 3.2.0make menuconfigDevice Drivers --->[*] Network device supp…

构建LAMP平台及应用系统

LANP架构指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包括linux操作系统、apache网站服务器、mysql数据库服务器、PHP&#xff08;或Perl、Python&#xff09;网页编程语言。在构建LAMP平台时…

pyqt2_官网教程

sklearn实战-乳腺癌细胞数据挖掘&#xff08;博主亲自录制视频&#xff09; https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare Articles You can find a collection of P…

Windows10安装WSL2和Ubuntu的过程

因为在Windows10环境中安装了2个相同的包导致冲突&#xff0c;所以想到了通过WSL2Docker的方式进行编程开发。因为Docker Desktop直接安装就行了&#xff0c;不做介绍。本文主要介绍WSL2和Ubuntu的安装过程。一.安装前的环境准备1.升级Windows系统因为低于某个版本号不支持WSL2…

Hyper-V数据文件丢失解决方案(有图有真相)

一、Hyper-V虚拟化故障概述 1、虚拟机环境故障虚拟化环境为ESXI虚拟化服务器&#xff0c;虚拟机环境&#xff0c;虚拟机的硬盘文件和配置文件放在北京某服务器托管公司的DELL MD3200存储中&#xff08;存储由5块容量为600G的硬盘组成raid磁盘阵列&#xff09;。该存储中4块硬盘…

SQL小技巧,动态输出本周各天日期

SET DATEFIRST 1; --设置周一为每周第一天 SELECT DATEFIRST;WITH w AS(SELECTCONVERT(varchar(10),T.[Date],120) AS [Date],DATENAME(weekday, T.[Date] ) AS [Week],DATEPART(WK, T.[Date]) AS WeekIndexFROM(SELECTDATEADD(DAY, number, DATEADD(wk, DATEDIFF(wk, 0, get…

开源的价值观与文化的传递

| 作者&#xff1a;Sharan Foga, Apache 软件基金会董事&#xff08;2021 届、2022 届&#xff09;&#xff0c;曾亲身来到 2019 中国开源年会&#xff08;COSCon19&#xff09;以本文内容发表主题演讲。| 翻译&#xff1a;刘天栋.Ted&#xff0c;徐红伟.stronghx| 审阅&#x…

用python来更改小伙伴的windows开机密码,不给10块不给开机

今天教大家用python脚本来控制小伙伴们windows电脑的开机密码。没错就是神不知鬼不觉&#xff0c;用random()随机生成的密码&#xff0c;只有你自己知道哦~ 代码呢分两部分&#xff0c;一部分是client端跟server端两个。你只需要想办法让小伙伴运行你的client端脚本就OK啦。不过…

el-upload 防止选择上传重复文件

<el-uploadref"uploadRef"multipledragaction"":auto-upload"false":file-list"msgPara.MsgFileList":on-change"handleFileChanged" ><el-button type"primary">选择文件</el-button> </el…

jmete 学习--基础之名词解释

一.jmeter 体系结构 1.名词解释 元件 jmemter工具菜单中的一个子菜单&#xff0c;如http请求&#xff0c;事务控制器等&#xff0c;就是一个元件。 组件 一组元件的集合&#xff0c;比如逻辑控制器中有事务控制器&#xff0c;仅一次控制器等&#xff0c;这些都是hi元件&#x…

Virtual script not found, may missing <script lang=“ts“> / “allowJs“: true / jsconfig.json.volar

解决办法&#xff1a; 在 jsconfig.json 配置文件中设置 "allowJs": true 如果没有jsconfig.json文件&#xff0c;直接在项目要目录创建一个&#xff0c;添加如下配置内容即可&#xff1a; /** Title: This is a file for ……* Author: JackieZheng* Date: 2022…

协鑫集成“熄灯工厂”装上ET工业大脑,验证订单命中率可提高3.99%

4月26日的云栖大会南京峰会&#xff0c;协鑫集成宣布&#xff0c;与阿里云ET工业大脑合作后&#xff0c;通过人工智能验证的订单命中率可提高3.99%。 协鑫集成是全球一线组件制造商&#xff0c;积极致力于推进自主创新与智能制造&#xff0c;综合运用信息通讯、物联网、大数据决…

pip install mysql-connector 安装出错

一、MySQL Connector/Python 2.2.3 的变化&#xff1a; 之前 mysql 官方说MySQL Connector/Python 是纯python语言写的&#xff0c;但是呢&#xff01; 这个问题在2.2.3中变天了&#xff1b; 以下是MySQL Connector/Python 2.2.3 是变更记录 Changes in MySQL Connector/Python…

2022世界传感器大会 | 龙芯中科发布龙芯2K0500多功能SoC芯片及解决方案

8月21日&#xff0c;由工业和信息化部、中国科学技术协会、河南省人民政府共同主办的2022世界传感器大会在郑州开幕&#xff0c;众多诺奖、图灵奖获得者、海内外院士和专家学者出席&#xff0c;全球传感器领域最具影响力的相关企业参加。龙芯中科董事长胡伟武在大会开幕式发表主…

Vue3 配置config文件,打包后随意修改配置,无需重新打包和重启

在public目录创建config.json文件&#xff0c;名字随便起。 {"AppVersion": "1.0","AppTitle": "这里是程序名称" } 修改AppTitle&#xff1a; {"AppVersion": "1.0","AppTitle": "这里是修改后的…

在Vue3中使用Element Plus Icon图标的几种方式

安装 Element Plus $ npm install element-plus/icons在main.js 引入 import * as ElIcon from element-plus/icons-vueObject.keys(ElIcon).forEach((key) > {app.component(key, ElIcon[key]) }) 方式一&#xff1a;通过 icon"el-icon-plus" 使用 <!-- …

Qt 打印机操作

2019独角兽企业重金招聘Python工程师标准>>> 配置文件加入打印机支持&#xff1a; QT printsupport 1、打印图片 打印图片所需头文件&#xff1a; #include <QPixmap> #include <QPrinter> #include <QPainter> 打印图片代码&#xff1a; QStrin…

spark集群详细搭建过程及遇到的问题解决(四)

在spark集群详细搭建过程及遇到的问题解决&#xff08;三&#xff09;中&#xff0c;我们将讲述了hadoop的安装过程&#xff0c;在本文中将主要讲述spark的安装配置过程。sparkmaster:~/spark$ cd hadoop sparkmaster:~/spark/hadoop$ cd $SPARK_HOME/conf sparkmaster:~/spark…

k8s 读书笔记 - 深入掌握 Pod

什么是 PodPod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。在同一个 context 下&#xff0c;应用可能还会有独立的 cgroup 隔离机制&#xff0c;一个 Pod 是一个容器环境下的 “逻辑主机”。Pod 是一组容器单元&#xff0c; 这些容器共享存储、网络、以及怎…