-
-
Notifications
You must be signed in to change notification settings - Fork 117
Description
Current state
In our current state, the TestContext and ITestRenderer offers a DisposeComponents method that basically removes all components from the RenderTree so they get disposed of. That has three flaws:
- It is an all-or-nothing approach. There is no way of controlling which component should be removed.
- The API is rather ugly as we expose
DisposeComponentsto too many hierarchies (and objects). - If we decide to go with a
Rendererinstance perRendercall ourDisposeComponentswouldn't work anymore.
Fine-grained disposing
With v2 we have the ability to correct such things. The Renderer (from Blazor itself) offers a RemoveRootComponent that allows us the remove specific elements from the tree.
API
The API would sit on top of the IRenderFragment type and some API inside the TestRenderer:
TestRenderer.cs
internal void RemoveComponent(IRenderedFragment fragment)
=> RemoveRootComponent(fragment.ComponentId);Extensions for IRenderFragment:
public static void DisposeComponent(this IRenderedFragment fragment)
{
ArgumentNullException.ThrowIfNull(fragment);
var renderer = fragment.Services.GetRequiredService<TestRenderer>();
renderer.RemoveComponent(fragment.ComponentId);
}Usage
The usage would be fairly trivial:
var cut = RenderComponent<Component>();
cut.DisposeComponent();Alternative Design
Alternatively, we already have a IDisposable implementation inside IRenderFragment. That said, we could leverage this:
internal class RenderedFragment : IRenderedFragment
{
public void Dispose()
{
// Here normal dispose logic
testRenderer.RemoveComponent(ComponentId);
}
}That would feel more natural to the language itself. It seems odd to have two dedicated functions taking care of disposing (from an outside point of view).
The inherent issue with this approach is that the markup is set to empty - anyway, there should be no check on the markup if your component gets disposed of.
As the IRenderFragment already has IDisposable that could lead to side effects for users that already do things like:
using var cut = RenderComponent<...>();Seems to be some usage like this: https://grep.app/search?q=using%20var.%2ARenderComponent®exp=true&case=true&filter[lang][0]=C%23.
What are your thoughts @egil ?
Edit: I am leaning towards the second approach of leveraging the already existing Dispose method.