Add TagHelperScopeManager for runtime.

- Also added an interface ITagHelperScopeManager so we can activate the type via DI.

#155
This commit is contained in:
NTaylorMullen 2014-09-25 01:34:21 -07:00 committed by N. Taylor Mullen
parent b1a3c8c1d4
commit 66aea52542
5 changed files with 89 additions and 6 deletions

View File

@ -62,6 +62,22 @@ namespace Microsoft.AspNet.Razor.Runtime
return GetString("TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull");
}
/// <summary>
/// Must call '{2}.{1}' before calling '{2}.{0}'.
/// </summary>
internal static string ScopeManager_EndCannotBeCalledWithoutACallToBegin
{
get { return GetString("ScopeManager_EndCannotBeCalledWithoutACallToBegin"); }
}
/// <summary>
/// Must call '{2}.{1}' before calling '{2}.{0}'.
/// </summary>
internal static string FormatScopeManager_EndCannotBeCalledWithoutACallToBegin(object p0, object p1, object p2)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ScopeManager_EndCannotBeCalledWithoutACallToBegin"), p0, p1, p2);
}
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

View File

@ -128,4 +128,7 @@
<data name="TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull" xml:space="preserve">
<value>Tag helper directive assembly name cannot be null or empty.</value>
</data>
<data name="ScopeManager_EndCannotBeCalledWithoutACallToBegin" xml:space="preserve">
<value>Must call '{2}.{1}' before calling '{2}.{0}'.</value>
</data>
</root>

View File

@ -9,15 +9,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <summary>
/// Class used to store information about a <see cref="ITagHelper"/>'s execution lifetime.
/// </summary>
public class TagHelpersExecutionContext
public class TagHelperExecutionContext
{
private readonly List<ITagHelper> _tagHelpers;
/// <summary>
/// Instantiates a new <see cref="TagHelpersExecutionContext"/>.
/// Instantiates a new <see cref="TagHelperExecutionContext"/>.
/// </summary>
/// <param name="tagName">The HTML tag name in the Razor source.</param>
public TagHelpersExecutionContext([NotNull] string tagName)
public TagHelperExecutionContext([NotNull] string tagName)
{
AllAttributes = new Dictionary<string, object>(StringComparer.Ordinal);
HTMLAttributes = new Dictionary<string, string>(StringComparer.Ordinal);

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <param name="context">Contains information associated with running <see cref="ITagHelper"/>s.</param>
/// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
/// <paramref name="context"/>'s <see cref="ITagHelper"/>s.</returns>
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelpersExecutionContext context)
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext context)
{
return await RunAsyncCore(context, string.Empty);
}
@ -29,13 +29,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <param name="bufferedBody">Contains the buffered content of the current HTML tag.</param>
/// <returns>Resulting <see cref="TagHelperOutput"/> from processing all of the
/// <paramref name="context"/>'s <see cref="ITagHelper"/>s.</returns>
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelpersExecutionContext context,
public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext context,
[NotNull] TextWriter bufferedBody)
{
return await RunAsyncCore(context, bufferedBody.ToString());
}
private async Task<TagHelperOutput> RunAsyncCore(TagHelpersExecutionContext executionContext, string outputContent)
private async Task<TagHelperOutput> RunAsyncCore(TagHelperExecutionContext executionContext, string outputContent)
{
var tagHelperContext = new TagHelperContext(executionContext.AllAttributes);
var tagHelperOutput = new TagHelperOutput(executionContext.TagName,

View File

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
/// <summary>
/// Class that manages <see cref="TagHelperExecutionContext"/> scopes.
/// </summary>
public class TagHelperScopeManager
{
private readonly Stack<TagHelperExecutionContext> _executionScopes;
/// <summary>
/// Instantiates a new <see cref="TagHelperScopeManager"/>.
/// </summary>
public TagHelperScopeManager()
{
_executionScopes = new Stack<TagHelperExecutionContext>();
}
/// <summary>
/// Starts a <see cref="TagHelperExecutionContext"/> scope.
/// </summary>
/// <param name="tagName">The HTML tag name that the scope is associated with.</param>
/// <returns>A <see cref="TagHelperExecutionContext"/> to use.</returns>
public TagHelperExecutionContext Begin(string tagName)
{
var executionContext = new TagHelperExecutionContext(tagName);
_executionScopes.Push(executionContext);
return executionContext;
}
/// <summary>
/// Ends a <see cref="TagHelperExecutionContext"/> scope.
/// </summary>
/// <returns>If the current scope is nested, the parent <see cref="TagHelperExecutionContext"/>.
/// <c>null</c> otherwise.</returns>
public TagHelperExecutionContext End()
{
if (_executionScopes.Count == 0)
{
throw new InvalidOperationException(
Resources.FormatScopeManager_EndCannotBeCalledWithoutACallToBegin(
nameof(End),
nameof(Begin),
nameof(TagHelperScopeManager)));
}
_executionScopes.Pop();
if (_executionScopes.Count != 0)
{
return _executionScopes.Peek();
}
return null;
}
}
}