Reputation: 3423
I am wondering if there is something similar to this in Blazor:
@injectScoped IMyService Service
So the injected instance will be created when the component is created and destroyed when the component is destroyed.
Any child component using the same @injectScoped
directive will receive the parent's instance, not the singleton (global) one created at the root.
I am still searching for how to achieve that in a Blazor Webassembly app.
Upvotes: 0
Views: 491
Reputation: 30310
Good question.
There's a problem in the Service Container implementation used by Blazor. It was designed for server-side rendering. Scoped
services match the scope of the page/Http request. In Blazor that represents the SPA session. There's no matching scope for a component/page. OwningComponentBase
was designed to fit this need, but it's useless in many situations - I explain why further down.
Your options depend on the nature of the service.
IDisposable/IAsyncDisposable
on ServiceIf your Service doesn't implement IDisposable/IAsyncDisposable
you can scope it as Transient
and then cascade it from the top level page/form.
IDisposable/IAsyncDisposable
on ServiceIf your Service implements IDisposable/IAsyncDisposable
you need to use ActivatorUtilities
to create an instance of the service/object with it's dependancies populated from the service container. This ensures the service container doesn't retain any references to the instance. You cascade this as above. Important - You are responsible for the disposal.
Neither of these are perfect. Cascading an object causes constant Render Tree Cascades: it's an object and the Render has no way of detecting changes.
OwningComponentBase
Any Scoped services that your service depends on are created in the same container: it is after all just a Scoped container. Take AuthenticationService. The instance in the SPA scoped container is the one your service needs, but instead it gets a new one with no user information. The same applies to Notification services, the NavigationManager and many others. It's useless, except in very specific circumstances.
My personal current solution is a ComponentServiceProvider
service that creates and manages service instances for the component. It's too lengthy to cover here in detail. There's a repo here: https://github.com/ShaunCurtis/Blazr.ComponentServiceProvider along with a more detailed discussion of the above.
Upvotes: 2
Reputation: 14613
OwningComponentBase
or OwningComponentBase<>
@inherits OwningComponentBase<SomeService>
<h3>SomeComponent</h3>
@code {
SomeService myService => base.Service;
}
Upvotes: 1