Blazor CascadingParameter 与单例 DependencyInjection
Posted
技术标签:
【中文标题】Blazor CascadingParameter 与单例 DependencyInjection【英文标题】:Blazor CascadingParameter vs singleton DependencyInjection 【发布时间】:2021-01-08 20:14:16 【问题描述】:我最近了解到,您可以通过将 Router
组件包装在提供程序 Microsoft doc 中来为整个项目提供 cascadingValues。这与使用单例模式的依赖注入有何不同? (我知道注入是如何工作的,我的意思是性能和架构方面)
你觉得哪个更好用?
【问题讨论】:
【参考方案1】:关于 CascadingValues 的性能影响已经进行了一些讨论。我可以推荐this article(这也是一个很好的教程)。
正如您所提到的,有两个方面:性能和架构。
性能
我发现 [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>
这个sn-p通俗易懂,很快就能看懂。如果你对单例服务做了同样的事情,你需要实现组件和服务之间的“通信”。最好实现订阅/取消订阅场景,可能使用事件或更高级的技术。您将需要编写自己的代码,并且再次不要忘记编写 IDisposable
的实现以取消订阅。
级联参数侧重于 UI
虽然单例服务是解决许多不同问题的非常通用的方法,但级联值是专门为解决 UI 更新问题而设计的。他们做得非常有效。对于AuthenticationState
,它使用专门的视图。
如果 Blazor 不仅仅与 UI 有关,那么还有争论的余地,但凭借现代、丰富的 GUI 功能,有时我们在应用程序内部采用了分层方法。因此,对于 UI,我指的是应用程序中最终负责渲染的部分。
服务可以在这个内部 UI 层之外使用,贯穿整个应用程序,然后也可以在 UI 中重用,而级联参数只能在组件内部使用。
级联参数是(主要是一种方式)
级联参数由组件“拥有”。通常是声明它的组件。从那时起,它被传递到树上。所有其他组件都可以使用它。没有直接、简单且可扩展的方法来更新子组件的值。正如我所说,大多数情况下都有办法做到这一点,但在我看来,这是一条肮脏的道路。
总结
与许多其他技术一样,答案是:这取决于用例。
自上而下的用法:级联值
组件需要更新值:服务
许多变化:如果容易超过性能影响,它高度依赖于树结构。
在内部 UI 层内外使用:服务
而且,解决此问题的另一种方法可能是 Blazor Component Bus
更新
除了 Just the benno 所说的之外,我还可以补充一点,CascadingValue 组件和 Singleton 服务在其范围方面存在根本区别。在 Blazor Server 应用程序中,单例服务在应用程序的整个生命周期、多个连接和多个浏览器中都是单例的……而 CascadingValue 组件的范围仅限于应用程序的当前实例。更改 CascadingValue 组件提供的对象的状态对应用程序的新实例没有影响。但是,如果您在应用程序的实例中更改单例服务的状态,此更改将传播到应用程序的其他实例。尝试想象将 CascadingAuthenticationState 组件的功能实现为 Singleton 服务而不是 CascadingValue 会产生什么影响。
【讨论】:
以上是关于Blazor CascadingParameter 与单例 DependencyInjection的主要内容,如果未能解决你的问题,请参考以下文章