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的主要内容,如果未能解决你的问题,请参考以下文章

Blazor 组件中所需的级联参数

如何在 IdentityServer4 上添加电话号码声明

Blazor University 介绍 - 什么是 Blazor?

WTM Blazor,Blazor开发利器

Blazor学习之旅初步了解Blazor

Blazor 应用程序 /_blazor/disconnect 状态码 400