Luk*_*164 8 c# dependency-injection razor blazor
我最近了解到,您可以通过将Router组件包装在提供程序Microsoft doc中来为整个项目提供 cascadingValues中来向整个项目提供 cascadingValues 。这与使用单例模式的依赖注入有何不同?(我知道注入是如何工作的,我的意思是性能和架构方面)
您认为使用哪个更好?
关于 CascadingValues 的性能影响存在一些讨论。我可以推荐这篇文章(这也是一篇很棒的教程)。
正如您提到的,有两个方面:性能和架构。
表现
我认为与“正常”字段和属性[CascadingParameter]相比成本高昂。[Parameter]树中的每个组件都订阅更改[CascadingParameter]。如果值发生变化,ParamtersSet就会开始一个新的循环,这可能会导致调用渲染树并检查 DOM 中的某些内容是否需要更改。因此,即使不需要重新渲染,得出这个结论的过程也会消耗时间。组件越多,树的深度越深,这个过程就越慢。
建筑学
讨论这方面,我们可以思考一下CascadingAuthenticationState。它是 Blazor 身份验证框架的一部分,提供检查用户是否经过身份验证的访问权限。它被实现为级联值而不是单例。树下的组件(例如菜单)可以轻松地使用此值来为未经身份验证的用户隐藏/显示项目。为什么?
更改频率及其对 DOM 的影响
要回答的一个问题是级联值变化的影响。如果用户登录/注销,可以合理地假设这将触发巨大的 DOM 更改。因此,检查树的很大一部分(如果不是基于级联值放置的位置的整个树)并不是开销。
此外,可以猜测AuthenticationState在应用程序的生命周期内几乎不会发生任何变化。
简单
菜单组件使用 ,AuthorizeView其中使用 的级联参数Task<AuthenticationState>。
<AuthorizeView>
<Authorized>
<li><a href="/admin">Admin</a></li>
</Authorized>
<NotAuthorized>
<li><a href="authentication/login">Log in</a></li>
</NotAuthorized>
</AuthorizeView>
Run Code Online (Sandbox Code Playgroud)
这段代码很容易阅读,你可以很快理解它。如果您对单例服务执行相同的操作,则需要实现组件和服务之间的“通信”。最好使用事件或更先进的技术来实现订阅/取消订阅场景。您将需要编写自己的代码,并且再次不要忘记编写IDisposable取消订阅的实现。
级联参数主要集中在UI上
虽然单例服务是解决许多不同问题的非常通用的方法,但级联值是专门为解决 UI 更新问题而设计的。他们做得非常有效。在 的情况下AuthenticationState,它使用专门的视图。
如果 Blazor 不完全与 UI 相关,那么还有争论的余地,但通过现代、功能丰富的 GUI,有时我们在应用程序内部采用分层方法。因此,对于 UI,我指的是应用程序中最终负责渲染的部分。
服务可以在整个应用程序中在此内部 UI 层之外使用,然后也在 UI 中重用,而级联参数只能在组件内部使用。
级联参数是(大部分是一种方式)
级联参数由组件“拥有”。通常是声明它的组件。从那时起,它就会沿着树向下传递。所有其他组件都可以消耗它。没有直接、简单且可扩展的方法来更新子组件的值。正如我所说,大多数情况下,有很多方法可以做到这一点,但在我看来,这是一条肮脏的道路。
概括
与许多其他技术一样,答案是:这取决于用例。
自上而下的用法:级联值
组件需要更新值:service
许多变化:如果简单性超过对性能的影响,这在很大程度上取决于树结构。
在内部 UI 层的外部和内部使用:服务
而且,解决此问题的另一种方法可能是Blazor 组件总线
除了 Just the benno 所说的之外,我还可以补充一点,CascadingValue 组件和 Singleton 服务之间就其范围而言存在根本区别。Blazor Server App 中的单例服务在应用程序的整个生命周期、跨多个连接和跨多个浏览器都是单例的......而 CascadingValue 组件的范围仅限于应用程序的当前实例。更改 CascadingValue 组件提供的对象的状态对应用程序的新实例没有影响。但是,如果您更改应用程序实例中单例服务的状态,则此更改将传播到应用程序的其他实例。尝试想象将 CascadingAuthenticationState 组件的功能实现为 Singleton 服务而不是 CascadingValue 会产生什么影响。