Implement ParameterCollection
This commit is contained in:
parent
695ddc0fd6
commit
37217db73a
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single parameter supplied to an <see cref="IComponent"/>
|
||||
/// by its parent in the render tree.
|
||||
/// </summary>
|
||||
public readonly struct Parameter
|
||||
{
|
||||
private readonly RenderTreeFrame[] _frames;
|
||||
private readonly int _frameIndex;
|
||||
|
||||
internal Parameter(RenderTreeFrame[] frames, int currentIndex)
|
||||
{
|
||||
_frames = frames;
|
||||
_frameIndex = currentIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the parameter.
|
||||
/// </summary>
|
||||
public string Name
|
||||
=> _frames[_frameIndex].AttributeName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the parameter.
|
||||
/// </summary>
|
||||
public object Value
|
||||
=> _frames[_frameIndex].AttributeValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of parameters supplied to an <see cref="IComponent"/>
|
||||
/// by its parent in the render tree.
|
||||
/// </summary>
|
||||
public readonly struct ParameterCollection
|
||||
{
|
||||
private readonly RenderTreeFrame[] _frames;
|
||||
private readonly int _ownerIndex;
|
||||
|
||||
internal ParameterCollection(RenderTreeFrame[] frames, int ownerIndex)
|
||||
{
|
||||
_frames = frames;
|
||||
_ownerIndex = ownerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the <see cref="ParameterCollection"/>.
|
||||
/// </summary>
|
||||
/// <returns>The enumerator.</returns>
|
||||
public ParameterEnumerator GetEnumerator()
|
||||
=> new ParameterEnumerator(_frames, _ownerIndex);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// An enumerator that iterates through a <see cref="ParameterCollection"/>.
|
||||
/// </summary>
|
||||
public struct ParameterEnumerator
|
||||
{
|
||||
private readonly RenderTreeFrame[] _frames;
|
||||
private readonly int _ownerIndex;
|
||||
private readonly int _ownerDescendantsEndIndexExcl;
|
||||
private int _currentIndex;
|
||||
|
||||
internal ParameterEnumerator(RenderTreeFrame[] frames, int ownerIndex)
|
||||
{
|
||||
_frames = frames;
|
||||
_ownerIndex = ownerIndex;
|
||||
_ownerDescendantsEndIndexExcl = ownerIndex + _frames[ownerIndex].ElementSubtreeLength;
|
||||
_currentIndex = ownerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value of the enumerator.
|
||||
/// </summary>
|
||||
public Parameter Current
|
||||
=> _currentIndex > _ownerIndex
|
||||
? new Parameter(_frames, _currentIndex)
|
||||
: throw new InvalidOperationException("Iteration has not yet started.");
|
||||
|
||||
/// <summary>
|
||||
/// Instructs the enumerator to move to the next value in the sequence.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool MoveNext()
|
||||
{
|
||||
// Stop iteration if you get to the end of the owner's descendants...
|
||||
var nextIndex = _currentIndex + 1;
|
||||
if (nextIndex == _ownerDescendantsEndIndexExcl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... or if you get to its first non-attribute descendant (because attributes
|
||||
// are always before any other type of descendant)
|
||||
if (_frames[nextIndex].FrameType != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_currentIndex = nextIndex;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Blazor.Components;
|
||||
using Microsoft.AspNetCore.Blazor.RenderTree;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Test
|
||||
{
|
||||
public class ParameterCollectionTest
|
||||
{
|
||||
[Fact]
|
||||
public void CanInitializeUsingComponentWithNoDescendants()
|
||||
{
|
||||
// Arrange
|
||||
var frames = new[]
|
||||
{
|
||||
RenderTreeFrame.ChildComponent<FakeComponent>(0).WithComponentSubtreeLength(1)
|
||||
};
|
||||
var parameterCollection = new ParameterCollection(frames, 0);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(ToEnumerable(parameterCollection));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanInitializeUsingElementWithNoDescendants()
|
||||
{
|
||||
// Arrange
|
||||
var frames = new[]
|
||||
{
|
||||
RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(1)
|
||||
};
|
||||
var parameterCollection = new ParameterCollection(frames, 0);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(ToEnumerable(parameterCollection));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerationStopsAtEndOfOwnerDescendants()
|
||||
{
|
||||
// Arrange
|
||||
var attribute1Value = new object();
|
||||
var attribute2Value = new object();
|
||||
var frames = new[]
|
||||
{
|
||||
RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3),
|
||||
RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value),
|
||||
RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value),
|
||||
// Although RenderTreeBuilder doesn't let you add orphaned attributes like this,
|
||||
// still want to verify that ParameterCollection doesn't attempt to read past the
|
||||
// end of the owner's descendants
|
||||
RenderTreeFrame.Attribute(3, "orphaned attribute", "value")
|
||||
};
|
||||
var parameterCollection = new ParameterCollection(frames, 0);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(ToEnumerable(parameterCollection),
|
||||
AssertParameter("attribute 1", attribute1Value),
|
||||
AssertParameter("attribute 2", attribute2Value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnumerationStopsAtEndOfOwnerAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var attribute1Value = new object();
|
||||
var attribute2Value = new object();
|
||||
var frames = new[]
|
||||
{
|
||||
RenderTreeFrame.Element(0, "some element").WithElementSubtreeLength(3),
|
||||
RenderTreeFrame.Attribute(1, "attribute 1", attribute1Value),
|
||||
RenderTreeFrame.Attribute(2, "attribute 2", attribute2Value),
|
||||
RenderTreeFrame.Element(3, "child element").WithElementSubtreeLength(2),
|
||||
RenderTreeFrame.Attribute(4, "child attribute", "some value")
|
||||
};
|
||||
var parameterCollection = new ParameterCollection(frames, 0);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(ToEnumerable(parameterCollection),
|
||||
AssertParameter("attribute 1", attribute1Value),
|
||||
AssertParameter("attribute 2", attribute2Value));
|
||||
}
|
||||
|
||||
private Action<Parameter> AssertParameter(string expectedName, object expectedValue)
|
||||
{
|
||||
return parameter =>
|
||||
{
|
||||
Assert.Equal(expectedName, parameter.Name);
|
||||
Assert.Same(expectedValue, parameter.Value);
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<Parameter> ToEnumerable(ParameterCollection parameterCollection)
|
||||
{
|
||||
foreach (var item in parameterCollection)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
private class FakeComponent : IComponent
|
||||
{
|
||||
public void Init(RenderHandle renderHandle)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue