From 41aae0b7e681c7ebf18faef8ed05b34c62d01445 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Fri, 16 Feb 2018 09:16:21 +0000 Subject: [PATCH] Add ability to append RenderFragment into a RenderTreeBuilder --- .../RenderTree/RenderTreeBuilder.cs | 19 +++++++++++++ .../RenderTreeBuilderTest.cs | 27 +++++++++++++++++++ .../BasicTestApp/RenderBlockComponent.cs | 4 +-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs index 2aa8808f5a..f71cc4c92a 100644 --- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs +++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeBuilder.cs @@ -65,6 +65,25 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree public void AddContent(int sequence, string textContent) => Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty)); + /// + /// Appends frames representing an arbitrary fragment of content. + /// + /// An integer that represents the position of the instruction in the source code. + /// Content to append. + public void AddContent(int sequence, RenderFragment fragment) + { + if (fragment != null) + { + // We surround the fragment with a region delimiter to indicate that the + // sequence numbers inside the fragment are unrelated to the sequence numbers + // outside it. If we didn't do this, the diffing logic might produce inefficient + // diffs depending on how the sequence numbers compared. + OpenRegion(sequence); + fragment(this); + CloseRegion(); + } + } + /// /// Appends a frame representing text content. /// diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs index 76ef5d71e9..3bba6922a7 100644 --- a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs +++ b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeBuilderTest.cs @@ -342,6 +342,33 @@ namespace Microsoft.AspNetCore.Blazor.Test frame => AssertFrame.Text(frame, "Goodbye", 6)); } + [Fact] + public void CanAddFragments() + { + // Arrange + var builder = new RenderTreeBuilder(new TestRenderer()); + RenderFragment fragment = fragmentBuilder => + { + fragmentBuilder.AddContent(0, "Hello from the fragment"); + fragmentBuilder.OpenElement(1, "Fragment element"); + fragmentBuilder.AddContent(2, "Some text"); + fragmentBuilder.CloseElement(); + }; + + // Act + builder.OpenElement(10, "parent"); + builder.AddContent(11, fragment); + builder.CloseElement(); + + // Assert + Assert.Collection(builder.GetFrames(), + frame => AssertFrame.Element(frame, "parent", 5, 10), + frame => AssertFrame.Region(frame, 4, 11), + frame => AssertFrame.Text(frame, "Hello from the fragment", 0), + frame => AssertFrame.Element(frame, "Fragment element", 2, 1), + frame => AssertFrame.Text(frame, "Some text", 2)); + } + [Fact] public void CanClear() { diff --git a/test/testapps/BasicTestApp/RenderBlockComponent.cs b/test/testapps/BasicTestApp/RenderBlockComponent.cs index aaf454e288..7088aad36d 100644 --- a/test/testapps/BasicTestApp/RenderBlockComponent.cs +++ b/test/testapps/BasicTestApp/RenderBlockComponent.cs @@ -48,9 +48,7 @@ namespace BasicTestApp if (_showRegion) { - builder.OpenRegion(3); - _exampleContent(builder); - builder.CloseRegion(); + builder.AddContent(3, _exampleContent); } builder.OpenElement(4, "button");