Add TagHelper registration system.
- This registration system accepts tag descriptors that it then uses to feed requests for tag helpers. - Added some infrastructure pieces that are used to build up valid tag helper descriptors. #70
This commit is contained in:
parent
a9f6a63e7f
commit
555615f60e
|
|
@ -0,0 +1,12 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Razor
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
|
||||
internal sealed class NotNullAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines how a tag helper will utilize its inner HTML.
|
||||
/// </summary>
|
||||
public enum ContentBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the tag helper will not modify its inner HTML in any way. This is the default
|
||||
/// <see cref="ContentBehavior"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
|
||||
/// appended to content its children generate.
|
||||
/// </summary>
|
||||
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
||||
Append,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the tag helper will modify its HTML content. Therefore this <see cref="ContentBehavior"/>
|
||||
/// enables the tag helper to examine the content its children generate.
|
||||
/// </summary>
|
||||
/// <remarks>Children of the current tag helper will execute before the current tag helper.</remarks>
|
||||
Modify,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to be
|
||||
/// prepended to the content its children generate.
|
||||
/// </summary>
|
||||
/// <remarks>Children of the current tag helper will execute after the current tag helper.</remarks>
|
||||
Prepend,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the tag helper wants anything within its tag builder's inner HTML to
|
||||
/// replace any HTML inside of it.
|
||||
/// </summary>
|
||||
/// <remarks>Children of the current tag helper will not execute.</remarks>
|
||||
Replace,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// 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.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// A metadata class describing a tag helper attribute.
|
||||
/// </summary>
|
||||
public class TagHelperAttributeDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="TagHelperAttributeDescriptor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="attributeName">The HTML attribute name.</param>
|
||||
/// <param name="propertyInfo">The <see cref="System.Reflection.PropertyInfo"/> for the tag
|
||||
/// helper attribute</param>
|
||||
public TagHelperAttributeDescriptor(string attributeName,
|
||||
PropertyInfo propertyInfo)
|
||||
{
|
||||
AttributeName = attributeName;
|
||||
PropertyInfo = propertyInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The HTML attribute name.
|
||||
/// </summary>
|
||||
public string AttributeName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the CLR property name that corresponds to the HTML attribute name.
|
||||
/// </summary>
|
||||
public string AttributePropertyName
|
||||
{
|
||||
get
|
||||
{
|
||||
return PropertyInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Reflection.PropertyInfo"/> for the tag helper attribute
|
||||
/// </summary>
|
||||
public PropertyInfo PropertyInfo { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// 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;
|
||||
using Microsoft.Internal.Web.Utils;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// A metadata class describing a tag helper.
|
||||
/// </summary>
|
||||
public class TagHelperDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="TagHelperDescriptor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="tagName">The tag name that the tag helper targets. '*' indicates a catch-all
|
||||
/// <see cref="TagHelperDescriptor"/> which applies to every HTML tag.</param>
|
||||
/// <param name="tagHelperName">The full name of the tag helper class.</param>
|
||||
/// <param name="contentBehavior">The <see cref="TagHelpers.ContentBehavior"/>
|
||||
/// of the tag helper.</param>
|
||||
public TagHelperDescriptor(string tagName,
|
||||
string tagHelperName,
|
||||
ContentBehavior contentBehavior)
|
||||
{
|
||||
TagName = tagName;
|
||||
TagHelperName = tagHelperName;
|
||||
ContentBehavior = contentBehavior;
|
||||
Attributes = new List<TagHelperAttributeDescriptor>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tag name that the tag helper should target.
|
||||
/// </summary>
|
||||
public string TagName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full name of the tag helper class.
|
||||
/// </summary>
|
||||
public string TagHelperName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TagHelpers.ContentBehavior"/> of the tag helper.
|
||||
/// </summary>
|
||||
public ContentBehavior ContentBehavior { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of attributes the tag helper expects.
|
||||
/// </summary>
|
||||
public virtual List<TagHelperAttributeDescriptor> Attributes { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// 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;
|
||||
using System.Linq;
|
||||
using Microsoft.Internal.Web.Utils;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables retrieval of <see cref="TagHelperDescriptor"/>'s.
|
||||
/// </summary>
|
||||
public class TagHelperDescriptorProvider
|
||||
{
|
||||
private const string CatchAllDescriptorTarget = "*";
|
||||
|
||||
private static readonly TagHelperDescriptorComparer DefaultTagHelperDescriptorComparer =
|
||||
new TagHelperDescriptorComparer();
|
||||
|
||||
private IDictionary<string, HashSet<TagHelperDescriptor>> _registrations;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="TagHelperDescriptorProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">The descriptors that the <see cref="TagHelperDescriptorProvider"/> will pull from.</param>
|
||||
public TagHelperDescriptorProvider(IEnumerable<TagHelperDescriptor> descriptors)
|
||||
{
|
||||
_registrations = new Dictionary<string, HashSet<TagHelperDescriptor>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Populate our registrations
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
Register(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all tag helpers that match the given <paramref name="tagName"/>.
|
||||
/// </summary>
|
||||
/// <param name="tagName">The name of the HTML tag to match. Providing a '*' tag name
|
||||
/// retrieves catch-all <see cref="TagHelperDescriptor"/>s (descriptors that target every tag).</param>
|
||||
/// <returns><see cref="TagHelperDescriptor"/>s that apply to the given <paramref name="tagName"/>.
|
||||
/// Will return an empty <see cref="Enumerable" /> if no <see cref="TagHelperDescriptor"/>s are
|
||||
/// found.</returns>
|
||||
public IEnumerable<TagHelperDescriptor> GetTagHelpers(string tagName)
|
||||
{
|
||||
HashSet<TagHelperDescriptor> descriptors;
|
||||
|
||||
// Ensure there's an ISet to use.
|
||||
if (!_registrations.TryGetValue(CatchAllDescriptorTarget, out descriptors))
|
||||
{
|
||||
descriptors = new HashSet<TagHelperDescriptor>();
|
||||
}
|
||||
|
||||
// If the requested tag name is the catch-all target, we should short circuit.
|
||||
if (tagName.Equals(CatchAllDescriptorTarget, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
// If we have a tag name associated with the requested name, return the descriptors +
|
||||
// all of the catch-all descriptors.
|
||||
if (_registrations.TryGetValue(tagName, out var matchingDescriptors))
|
||||
{
|
||||
return matchingDescriptors.Concat(descriptors);
|
||||
}
|
||||
|
||||
// We couldn't any descriptors associated with the requested tag name, return all
|
||||
// of the "catch-all" tag descriptors (there may not be any).
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private void Register(TagHelperDescriptor descriptor)
|
||||
{
|
||||
HashSet<TagHelperDescriptor> descriptorSet;
|
||||
|
||||
// Ensure there's a List to add the descriptor to.
|
||||
if (!_registrations.TryGetValue(descriptor.TagName, out descriptorSet))
|
||||
{
|
||||
descriptorSet = new HashSet<TagHelperDescriptor>(DefaultTagHelperDescriptorComparer);
|
||||
_registrations[descriptor.TagName] = descriptorSet;
|
||||
}
|
||||
|
||||
descriptorSet.Add(descriptor);
|
||||
}
|
||||
|
||||
private class TagHelperDescriptorComparer : IEqualityComparer<TagHelperDescriptor>
|
||||
{
|
||||
public bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
|
||||
{
|
||||
return descriptorX.TagHelperName == descriptorY.TagHelperName &&
|
||||
descriptorX.TagName == descriptorY.TagName &&
|
||||
descriptorX.ContentBehavior == descriptorY.ContentBehavior;
|
||||
}
|
||||
|
||||
public int GetHashCode(TagHelperDescriptor descriptor)
|
||||
{
|
||||
return HashCodeCombiner.Start()
|
||||
.Add(descriptor.TagName)
|
||||
.Add(descriptor.TagHelperName)
|
||||
.Add(descriptor.ContentBehavior)
|
||||
.CombinedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue