简体   繁体   English

Blazor 级联参数与 singleton 依赖注入

[英]Blazor CascadingParameter vs singleton DependencyInjection

I have recently learned that you can provide cascadingValues to the entire project by wrapping the Router component in the provider Microsoft doc .我最近了解到,您可以通过将Router组件包装在提供程序Microsoft doc中来为整个项目提供 cascadingValues。 How is this different to using dependency injection with a singleton pattern?这与使用 singleton 模式的依赖注入有何不同? (I know how injection works, I mean performance and architecture wise) (我知道注入是如何工作的,我的意思是性能和架构方面)

Which do you think is better to use?你觉得哪个更好用?

There has been some discussion about the performance impact of CascadingValues.关于 CascadingValues 的性能影响已经有一些讨论。 I can recommend this article (it is an excellent tutorial as well).我可以推荐这篇文章(它也是一个很好的教程)。

As you mentioned, there are two aspects: performance and architecture.正如您所提到的,有两个方面:性能和架构。

Performance表现

I'd see [CascadingParameter] are costly compared to [Parameter] or "normal" fields and properties.我会看到[CascadingParameter][Parameter]或“普通”字段和属性相比成本高昂。 Each component down the tree, subscribe to the [CascadingParameter] changes.树下的每个组件,订阅[CascadingParameter]更改。 If the value changes, a new cycle of ParamtersSet is started, which could lead to a call to the render tree and check if something in DOM needs to be changed.如果值发生变化,则启动新的ParamtersSet循环,这可能会导致调用渲染树并检查 DOM 中的某些内容是否需要更改。 So, even if no rerendering is required, the process to reach this conclusion consumes time.因此,即使不需要重新渲染,得出这个结论的过程也会消耗时间。 The more components, the more depth the tree has, the slower this process becomes.组件越多,树的深度越大,这个过程就越慢。

Architecture建筑学

To discuss this aspect, we can think about the CascadingAuthenticationState .为了讨论这个方面,我们可以考虑CascadingAuthenticationState It is part of the authentication framework for Blazor and provides access to check whether a user is authenticated or not.它是 Blazor 身份验证框架的一部分,并提供检查用户是否通过身份验证的访问权限。 It is implemented as a cascading value instead of a singleton.它被实现为级联值,而不是 singleton。 Components down the tree, like menus, can easily use this value to hide/show items for non authenticated users.树下的组件(如菜单)可以轻松地使用此值来隐藏/显示未经过身份验证的用户的项目。 Why?为什么?

Frequency of change and impact to the DOM更改频率和对 DOM 的影响

A question to answer is regarding the impact of the change of a cascading value.要回答的问题是关于级联值变化的影响。 If a user logins/log out, it is reasonable to assume that this will trigger a huge DOM change.如果用户登录/注销,可以合理地假设这将触发巨大的 DOM 更改。 So, checking a huge part of the tree (if not the entire based on where the cascading value is placed) is not overhead.因此,检查树的很大一部分(如果不是基于级联值放置位置的全部)不是开销。

Besides, it is a good guess that there will be few changes to AuthenticationState during the lifetime of the application.此外,可以很好地猜测AuthenticationState在应用程序的生命周期内几乎不会发生变化。

Simplicity简单

The menu component uses the AuthorizeView which uses the cascading parameter of Task<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>

This snippet is easy to read, and you can understand it very quickly.这个片段很容易阅读,你可以很快理解它。 If you did the same thing with a singleton service, you would need to implement the "communication" between component and service.如果您对 singleton 服务执行相同操作,则需要实现组件和服务之间的“通信”。 It would be best to implement a subscribe/unsubscribe scenario, maybe using events or more advanced technologies.最好实现订阅/取消订阅场景,可能使用事件或更高级的技术。 You will need to write your own code, and again don't forget to write your implementation of IDisposable to unsubscribe.您将需要编写自己的代码,并且再次不要忘记编写IDisposable的实现来取消订阅。

Cascading parameters are focused on UI级联参数侧重于 UI

While a singleton service is a very generic approach to solve many different issues, cascading values are specially designed to solve UI update problems.虽然 singleton 服务是解决许多不同问题的非常通用的方法,但级联值专门用于解决 UI 更新问题。 They are doing it very efficiently.他们做得非常有效。 In the case of the AuthenticationState , it uses a specialized view.AuthenticationState的情况下,它使用专门的视图。

There is space for arguments if Blazor isn't all about UI, but with modern, rich features GUI, sometimes we have a layered approach inside the application.如果 Blazor 不仅仅与 UI 有关,但具有现代、丰富功能的 GUI,有时我们在应用程序内部有分层方法,则 arguments 有空间。 So, with UI, I mean the part of the application ultimately responsible for rendering.因此,对于 UI,我指的是应用程序中最终负责渲染的部分。

Services could be used outside of this inner UI layer, through the entire application, and then reused in the UI as well, while cascading parameters could only be used inside components.服务可以在这个内部 UI 层之外,通过整个应用程序使用,然后在 UI 中也可以重用,而级联参数只能在组件内部使用。

Cascading parameters are (mostly one way)级联参数是(主要是一种方式)

A cascading parameter is "owned" by a component.级联参数由组件“拥有”。 Usually, the component where it is declared.通常是声明它的组件。 From that point, it is passed down the tree.从那时起,它被传递到树上。 All other components can consume it.所有其他组件都可以使用它。 There is no straightforward, easy, and scalable way to update a value from a child component.没有直接、简单且可扩展的方法来更新子组件的值。 As I said, mostly, there are ways to do it, but it is a dirty path, in my view.正如我所说,大多数情况下,有办法做到这一点,但在我看来,这是一条肮脏的道路。

Summary概括

As with a lot of other technologies, the answer is: It depends on the use case.与许多其他技术一样,答案是:这取决于用例。

top-down usage : cascading values自上而下的用法:级联值

Components need to update the value : service组件需要更新值:服务

many changes: It highly depends on the tree structures if easiness outweighs the performance impact.许多变化:如果容易超过性能影响,它高度依赖于树结构。

use outside and inside the inner UI layer : service在内部 UI 层内外使用:服务

And, another approach to this problem could be something like Blazor Component Bus并且,解决此问题的另一种方法可能是Blazor 组件总线

Update更新

In addition to what was said by Just the benno, I may add that there is a fundamental difference between a CascadingValue component and a Singleton service regarding their scope.除了 Just the benno 所说的之外,我还可以补充一点,CascadingValue 组件和 Singleton 服务在 scope 方面存在根本区别。 A Singleton service, in Blazor Server App, is singleton across the lifetime of the application, across multiple connections, and across multiple browsers... while CascadingValue component is scoped to the current instance of your app. Singleton 服务,在 Blazor 服务器应用程序中,是 singleton 整个应用程序的生命周期,跨多个连接,跨多个浏览器...而您的 app.current 组件的范围为Changing the state of an object provided by a CascadingValue component has no effect on a new instance of the app.更改 CascadingValue 组件提供的 object 的 state 对应用程序的新实例没有影响。 But if you change the state of a Singleton service in an instance of your app, this change will be propagated to other instances of your app.但是,如果您在应用程序实例中更改 Singleton 服务的 state,则此更改将传播到应用程序的其他实例。 Try to imagine what would be the implications of implementing the functionality of the CascadingAuthenticationState component as a Singleton service rather than CascadingValue.尝试想象将 CascadingAuthenticationState 组件的功能实现为 Singleton 服务而不是 CascadingValue 会产生什么影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM