Cache XML file information when creating design time based `TagHelperDescriptor`s.

- Prior to this change we'd hit the disk every time we'd create a `TagHelperDesignTimeDescriptor` to locate an assemblies XML files.
- Did not want to tie the XML cache to a static member in-case a user updates their XML information between parses. Therefore, changed `TagHelperDescriptorFactory` and `TagHelperDesignTimeDescriptorFactory` to no longer be static.
- Put the same `TagHeleprDescriptorFactory` extensibility point as we had for its counterpart `TagHelperTypeResolver` to stay consistent. This involved making `CreateDescriptors` virtual and allowing it to be provided in the `TagHelperDescriptorResolver` constructor.

#630
This commit is contained in:
N. Taylor Mullen 2015-12-09 15:37:43 -08:00
parent 392871beb6
commit dbe4ce06f2
10 changed files with 261 additions and 127 deletions

View File

@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <summary>
/// Factory for <see cref="TagHelperDescriptor"/>s from <see cref="ITypeInfo"/>s.
/// </summary>
public static class TagHelperDescriptorFactory
public class TagHelperDescriptorFactory
{
private const string DataDashPrefix = "data-";
private const string TagHelperNameEnding = "TagHelper";
@ -33,29 +33,49 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private static readonly ITypeInfo StringTypeInfo = new RuntimeTypeInfo(typeof(string).GetTypeInfo());
#if !DOTNET5_4
private readonly TagHelperDesignTimeDescriptorFactory _designTimeDescriptorFactory;
#endif
private readonly bool _designTime;
// TODO: Investigate if we should cache TagHelperDescriptors for types:
// https://github.com/aspnet/Razor/issues/165
public static ICollection<char> InvalidNonWhitespaceNameCharacters { get; } = new HashSet<char>(
new[] { '@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*' });
/// <summary>
/// Instantiates a new <see cref="TagHelperDescriptorFactory"/>.
/// </summary>
/// <param name="designTime">
/// Indicates if <see cref="TagHelperDescriptor"/>s should be created for design time.
/// </param>
public TagHelperDescriptorFactory(bool designTime)
{
#if !DOTNET5_4
if (designTime)
{
_designTimeDescriptorFactory = new TagHelperDesignTimeDescriptorFactory();
}
#endif
_designTime = designTime;
}
/// <summary>
/// Creates a <see cref="TagHelperDescriptor"/> from the given <paramref name="typeInfo"/>.
/// </summary>
/// <param name="assemblyName">The assembly name that contains <paramref name="type"/>.</param>
/// <param name="typeInfo">The <see cref="ITypeInfo"/> to create a <see cref="TagHelperDescriptor"/> from.
/// </param>
/// <param name="designTime">Indicates if the returned <see cref="TagHelperDescriptor"/>s should include
/// design time specific information.</param>
/// <param name="errorSink">The <see cref="ErrorSink"/> used to collect <see cref="RazorError"/>s encountered
/// when creating <see cref="TagHelperDescriptor"/>s for the given <paramref name="typeInfo"/>.</param>
/// <returns>
/// A collection of <see cref="TagHelperDescriptor"/>s that describe the given <paramref name="typeInfo"/>.
/// </returns>
public static IEnumerable<TagHelperDescriptor> CreateDescriptors(
public virtual IEnumerable<TagHelperDescriptor> CreateDescriptors(
string assemblyName,
ITypeInfo typeInfo,
bool designTime,
ErrorSink errorSink)
{
if (typeInfo == null)
@ -68,12 +88,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
throw new ArgumentNullException(nameof(errorSink));
}
if (ShouldSkipDescriptorCreation(designTime, typeInfo))
if (ShouldSkipDescriptorCreation(typeInfo))
{
return Enumerable.Empty<TagHelperDescriptor>();
}
var attributeDescriptors = GetAttributeDescriptors(typeInfo, designTime, errorSink);
var attributeDescriptors = GetAttributeDescriptors(typeInfo, errorSink);
var targetElementAttributes = GetValidHtmlTargetElementAttributes(typeInfo, errorSink);
var allowedChildren = GetAllowedChildren(typeInfo, errorSink);
@ -83,8 +103,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
assemblyName,
attributeDescriptors,
targetElementAttributes,
allowedChildren,
designTime);
allowedChildren);
return tagHelperDescriptors.Distinct(TagHelperDescriptorComparer.Default);
}
@ -99,24 +118,23 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
attribute => ValidHtmlTargetElementAttributeNames(attribute, errorSink));
}
private static IEnumerable<TagHelperDescriptor> BuildTagHelperDescriptors(
private IEnumerable<TagHelperDescriptor> BuildTagHelperDescriptors(
ITypeInfo typeInfo,
string assemblyName,
IEnumerable<TagHelperAttributeDescriptor> attributeDescriptors,
IEnumerable<HtmlTargetElementAttribute> targetElementAttributes,
IEnumerable<string> allowedChildren,
bool designTime)
IEnumerable<string> allowedChildren)
{
TagHelperDesignTimeDescriptor typeDesignTimeDescriptor = null;
#if !DOTNET5_4
if (designTime)
if (_designTime)
{
var runtimeTypeInfo = typeInfo as RuntimeTypeInfo;
if (runtimeTypeInfo != null)
{
typeDesignTimeDescriptor =
TagHelperDesignTimeDescriptorFactory.CreateDescriptor(runtimeTypeInfo.TypeInfo.AsType());
_designTimeDescriptorFactory.CreateDescriptor(runtimeTypeInfo.TypeInfo.AsType());
}
}
#endif
@ -387,10 +405,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return validName;
}
private static IEnumerable<TagHelperAttributeDescriptor> GetAttributeDescriptors(
ITypeInfo type,
bool designTime,
ErrorSink errorSink)
private IEnumerable<TagHelperAttributeDescriptor> GetAttributeDescriptors(ITypeInfo type, ErrorSink errorSink)
{
var attributeDescriptors = new List<TagHelperAttributeDescriptor>();
@ -400,7 +415,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var accessibleProperties = type.Properties.Where(IsAccessibleProperty);
foreach (var property in accessibleProperties)
{
if (ShouldSkipDescriptorCreation(designTime, property))
if (ShouldSkipDescriptorCreation(property))
{
continue;
}
@ -415,7 +430,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
TagHelperAttributeDescriptor mainDescriptor = null;
if (property.HasPublicSetter)
{
mainDescriptor = ToAttributeDescriptor(property, attributeName, designTime);
mainDescriptor = ToAttributeDescriptor(property, attributeName);
if (!ValidateTagHelperAttributeDescriptor(mainDescriptor, type, errorSink))
{
// HtmlAttributeNameAttribute.Name is invalid. Ignore this property completely.
@ -443,7 +458,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
parentType: type,
errorSink: errorSink,
defaultPrefix: attributeName + "-",
designTime: designTime,
isInvalid: out isInvalid);
if (indexerDescriptor != null &&
!ValidateTagHelperAttributeDescriptor(indexerDescriptor, type, errorSink))
@ -509,9 +523,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameOrPrefix);
}
private static bool ShouldSkipDescriptorCreation(bool designTime, IMemberInfo memberInfo)
private bool ShouldSkipDescriptorCreation(IMemberInfo memberInfo)
{
if (designTime)
if (_designTime)
{
var editorBrowsableAttribute = memberInfo
.GetCustomAttributes<EditorBrowsableAttribute>()
@ -594,27 +608,22 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return isValid;
}
private static TagHelperAttributeDescriptor ToAttributeDescriptor(
IPropertyInfo property,
string attributeName,
bool designTime)
private TagHelperAttributeDescriptor ToAttributeDescriptor(IPropertyInfo property, string attributeName)
{
return ToAttributeDescriptor(
property,
attributeName,
property.PropertyType.FullName,
isIndexer: false,
isStringProperty: StringTypeInfo.Equals(property.PropertyType),
designTime: designTime);
isStringProperty: StringTypeInfo.Equals(property.PropertyType));
}
private static TagHelperAttributeDescriptor ToIndexerAttributeDescriptor(
private TagHelperAttributeDescriptor ToIndexerAttributeDescriptor(
IPropertyInfo property,
HtmlAttributeNameAttribute attributeNameAttribute,
ITypeInfo parentType,
ErrorSink errorSink,
string defaultPrefix,
bool designTime,
out bool isInvalid)
{
isInvalid = false;
@ -689,28 +698,26 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
attributeName: prefix,
typeName: dictionaryTypeArguments[1].FullName,
isIndexer: true,
isStringProperty: StringTypeInfo.Equals(dictionaryTypeArguments[1]),
designTime: designTime);
isStringProperty: StringTypeInfo.Equals(dictionaryTypeArguments[1]));
}
private static TagHelperAttributeDescriptor ToAttributeDescriptor(
private TagHelperAttributeDescriptor ToAttributeDescriptor(
IPropertyInfo property,
string attributeName,
string typeName,
bool isIndexer,
bool isStringProperty,
bool designTime)
bool isStringProperty)
{
TagHelperAttributeDesignTimeDescriptor propertyDesignTimeDescriptor = null;
#if !DOTNET5_4
if (designTime)
if (_designTime)
{
var runtimeProperty = property as RuntimePropertyInfo;
if (runtimeProperty != null)
{
propertyDesignTimeDescriptor =
TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(runtimeProperty.Property);
_designTimeDescriptorFactory.CreateAttributeDescriptor(runtimeProperty.Property);
}
}
#endif

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
};
private readonly TagHelperTypeResolver _typeResolver;
private readonly bool _designTime;
private readonly TagHelperDescriptorFactory _descriptorFactory;
/// <summary>
/// Instantiates a new instance of the <see cref="TagHelperDescriptorResolver"/> class.
@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// <param name="designTime">Indicates whether resolved <see cref="TagHelperDescriptor"/>s should include
/// design time specific information.</param>
public TagHelperDescriptorResolver(bool designTime)
: this(new TagHelperTypeResolver(), designTime)
: this(new TagHelperTypeResolver(), new TagHelperDescriptorFactory(designTime))
{
}
@ -41,12 +41,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// specified <paramref name="typeResolver"/>.
/// </summary>
/// <param name="typeResolver">The <see cref="TagHelperTypeResolver"/>.</param>
/// <param name="designTime">Indicates whether resolved <see cref="TagHelperDescriptor"/>s should include
/// design time specific information.</param>
public TagHelperDescriptorResolver(TagHelperTypeResolver typeResolver, bool designTime)
/// <param name="descriptorFactory">The <see cref="TagHelperDescriptorFactory"/>.</param>
public TagHelperDescriptorResolver(
TagHelperTypeResolver typeResolver,
TagHelperDescriptorFactory descriptorFactory)
{
_typeResolver = typeResolver;
_designTime = designTime;
_descriptorFactory = descriptorFactory;
}
/// <inheritdoc />
@ -137,7 +138,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Convert types to TagHelperDescriptors
var descriptors = tagHelperTypes.SelectMany(
type => TagHelperDescriptorFactory.CreateDescriptors(assemblyName, type, _designTime, errorSink));
type => _descriptorFactory.CreateDescriptors(assemblyName, type, errorSink));
return descriptors;
}

View File

@ -3,6 +3,7 @@
#if !DOTNET5_4 // Cannot accurately resolve the location of the documentation XML file in coreclr.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@ -10,6 +11,7 @@ using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Razor.Compilation.TagHelpers;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
@ -17,8 +19,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// Factory for providing <see cref="TagHelperDesignTimeDescriptor"/>s from <see cref="Type"/>s and
/// <see cref="TagHelperAttributeDesignTimeDescriptor"/>s from <see cref="PropertyInfo"/>s.
/// </summary>
public static class TagHelperDesignTimeDescriptorFactory
public class TagHelperDesignTimeDescriptorFactory
{
private readonly ConcurrentDictionary<int, XmlDocumentationProvider> _documentationProviderCache =
new ConcurrentDictionary<int, XmlDocumentationProvider>();
/// <summary>
/// Creates a <see cref="TagHelperDesignTimeDescriptor"/> from the given <paramref name="type"/>.
/// </summary>
@ -27,7 +32,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </param>
/// <returns>A <see cref="TagHelperDesignTimeDescriptor"/> that describes design time specific information
/// for the given <paramref name="type"/>.</returns>
public static TagHelperDesignTimeDescriptor CreateDescriptor(Type type)
public TagHelperDesignTimeDescriptor CreateDescriptor(Type type)
{
if (type == null)
{
@ -66,8 +71,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </param>
/// <returns>A <see cref="TagHelperAttributeDesignTimeDescriptor"/> that describes design time specific
/// information for the given <paramref name="propertyInfo"/>.</returns>
public static TagHelperAttributeDesignTimeDescriptor CreateAttributeDescriptor(
PropertyInfo propertyInfo)
public TagHelperAttributeDesignTimeDescriptor CreateAttributeDescriptor(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
{
@ -77,7 +81,6 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var id = XmlDocumentationProvider.GetId(propertyInfo);
var declaringAssembly = propertyInfo.DeclaringType.Assembly;
var documentationDescriptor = CreateDocumentationDescriptor(declaringAssembly, id);
if (documentationDescriptor != null)
{
return new TagHelperAttributeDesignTimeDescriptor
@ -90,31 +93,51 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return null;
}
private static DocumentationDescriptor CreateDocumentationDescriptor(Assembly assembly, string id)
private XmlDocumentationProvider GetXmlDocumentationProvider(Assembly assembly)
{
var assemblyLocation = assembly.Location;
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(assembly);
hashCodeCombiner.Add(CultureInfo.CurrentCulture);
var cacheKey = hashCodeCombiner.CombinedHash;
if (string.IsNullOrEmpty(assemblyLocation) && !string.IsNullOrEmpty(assembly.CodeBase))
var documentationProvider = _documentationProviderCache.GetOrAdd(cacheKey, valueFactory: _ =>
{
var uri = new UriBuilder(assembly.CodeBase);
var assemblyLocation = assembly.Location;
// Normalize the path to a UNC path. This will remove things like file:// from start of the uri.Path.
assemblyLocation = Uri.UnescapeDataString(uri.Path);
}
if (string.IsNullOrEmpty(assemblyLocation) && !string.IsNullOrEmpty(assembly.CodeBase))
{
var uri = new UriBuilder(assembly.CodeBase);
// Normalize the path to UNC path. This will remove things like file:// from start of uri.Path.
assemblyLocation = Uri.UnescapeDataString(uri.Path);
}
// Couldn't resolve a valid assemblyLocation.
if (string.IsNullOrEmpty(assemblyLocation))
{
return null;
}
var xmlDocumentationFile = GetXmlDocumentationFile(assembly, assemblyLocation);
// Only want to process the file if it exists.
if (xmlDocumentationFile != null)
{
return new XmlDocumentationProvider(xmlDocumentationFile.FullName);
}
// Couldn't resolve a valid assemblyLocation.
if (string.IsNullOrEmpty(assemblyLocation))
{
return null;
}
});
var xmlDocumentationFile = GetXmlDocumentationFile(assembly, assemblyLocation);
return documentationProvider;
}
// Only want to process the file if it exists.
if (xmlDocumentationFile != null)
private DocumentationDescriptor CreateDocumentationDescriptor(Assembly assembly, string id)
{
var documentationProvider = GetXmlDocumentationProvider(assembly);
if (documentationProvider != null)
{
var documentationProvider = new XmlDocumentationProvider(xmlDocumentationFile.FullName);
var summary = documentationProvider.GetSummary(id);
var remarks = documentationProvider.GetRemarks(id);

View File

@ -26,6 +26,12 @@
"frameworkAssemblies": {
"System.Xml": "4.0.0.0",
"System.Xml.Linq": "4.0.0.0"
},
"dependencies": {
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"type": "build",
"version": "1.0.0-*"
}
}
},
"dotnet5.4": {

View File

@ -37,12 +37,12 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert

View File

@ -25,12 +25,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name;
var expectedDescriptor =
CreateTagHelperDescriptor("object", "System.Object", objectAssemblyName);
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
objectAssemblyName,
GetTypeInfo(typeof(object)),
designTime: false,
errorSink: errorSink);
// Assert
@ -48,12 +48,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -137,12 +137,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: true);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: true,
errorSink: errorSink);
// Assert

View File

@ -88,12 +88,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -177,12 +177,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -262,12 +262,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -351,12 +351,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -587,12 +587,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime,
errorSink);
// Assert
@ -789,12 +789,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -838,12 +838,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
// Assert
@ -875,12 +875,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
CreateTagHelperAttributeDescriptor("Something-Else", validProperty2)
})
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(OverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -909,12 +909,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
CreateTagHelperAttributeDescriptor("Something-Else", validProperty2)
})
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(InheritedOverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -943,12 +943,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
CreateTagHelperAttributeDescriptor("Something-Else", validProperty2)
})
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(InheritedNotOverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -973,12 +973,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
TypeName = typeof(int).FullName
}
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(InheritedSingleAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1001,12 +1001,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
CreateTagHelperAttributeDescriptor("int-attribute", intProperty)
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(SingleAttributeTagHelper)),
designTime: false,
errorSink: new ErrorSink());
// Assert
@ -1030,12 +1030,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
CreateTagHelperAttributeDescriptor("valid-attribute", validProperty)
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(MissingAccessorTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1059,12 +1059,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
CreateTagHelperAttributeDescriptor("valid-attribute", validProperty)
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(NonPublicAccessorTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1091,12 +1091,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
TypeName = typeof(object).FullName
}
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(NotBoundAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1110,12 +1110,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(DuplicateAttributeNameTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1159,12 +1159,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
})
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(MultiTagTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1191,12 +1191,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
CreateTagHelperAttributeDescriptor("valid-attribute", validProp)
});
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(InheritedMultiTagTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1221,12 +1221,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(DuplicateTagNameTagHelper).FullName,
AssemblyName)
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(DuplicateTagNameTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1251,12 +1251,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeof(OverrideNameTagHelper).FullName,
AssemblyName),
};
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(typeof(OverrideNameTagHelper)),
designTime: false,
errorSink: errorSink);
// Assert
@ -1439,12 +1439,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var errorSink = new ErrorSink();
var factory = new TagHelperDescriptorFactory(designTime: false);
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
var descriptors = factory.CreateDescriptors(
AssemblyName,
GetTypeInfo(type),
designTime: false,
errorSink: errorSink);
// Assert

View File

@ -1381,7 +1381,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private class TestTagHelperDescriptorResolver : TagHelperDescriptorResolver
{
public TestTagHelperDescriptorResolver(TagHelperTypeResolver typeResolver)
: base(typeResolver, designTime: false)
: base(typeResolver, new TagHelperDescriptorFactory(designTime: false))
{
}

View File

@ -74,8 +74,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Type tagHelperType,
TagHelperDesignTimeDescriptor expectedDescriptor)
{
// Arrange
var factory = new TagHelperDesignTimeDescriptorFactory();
// Act
var descriptors = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
var descriptors = factory.CreateDescriptor(tagHelperType);
// Assert
Assert.Equal(expectedDescriptor, descriptors, TagHelperDesignTimeDescriptorComparer.Default);
@ -142,8 +145,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Type tagHelperType,
TagHelperDesignTimeDescriptor expectedDesignTimeDescriptor)
{
// Arrange
var factory = new TagHelperDesignTimeDescriptorFactory();
// Act
var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
var designTimeDescriptor = factory.CreateDescriptor(tagHelperType);
// Assert
Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
@ -219,17 +225,59 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
TagHelperDesignTimeDescriptor designTimeDescriptor;
var factory = new TagHelperDesignTimeDescriptorFactory();
// Act
using (new CultureReplacer(culture))
{
designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(tagHelperType);
designTimeDescriptor = factory.CreateDescriptor(tagHelperType);
}
// Assert
Assert.Equal(expectedDesignTimeDescriptor, designTimeDescriptor, TagHelperDesignTimeDescriptorComparer.Default);
}
[Fact]
public void CreateDescriptor_WithLocalizedType_CachesBasedOnCulture()
{
// Arrange
var factory = new TagHelperDesignTimeDescriptorFactory();
var expectedFRDesignTimeDescriptor = new TagHelperDesignTimeDescriptor
{
Summary = "fr-FR: " + TypeSummary,
Remarks = "fr-FR: " + TypeRemarks,
OutputElementHint = "p",
};
var expectedNLBEDesignTimeDescriptor = new TagHelperDesignTimeDescriptor
{
Summary = "nl-BE: " + TypeSummary,
Remarks = "nl-BE: " + TypeRemarks,
OutputElementHint = "p",
};
var tagHelperType = CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null);
TagHelperDesignTimeDescriptor frDesignTimeDescriptor, nlBEDesignTimeDescriptor;
// Act
using (new CultureReplacer("fr-FR"))
{
frDesignTimeDescriptor = factory.CreateDescriptor(tagHelperType);
}
using (new CultureReplacer("nl-BE"))
{
nlBEDesignTimeDescriptor = factory.CreateDescriptor(tagHelperType);
}
// Assert
Assert.Equal(
expectedFRDesignTimeDescriptor,
frDesignTimeDescriptor,
TagHelperDesignTimeDescriptorComparer.Default);
Assert.Equal(
expectedNLBEDesignTimeDescriptor,
nlBEDesignTimeDescriptor,
TagHelperDesignTimeDescriptorComparer.Default);
}
public static TheoryData CreateAttributeDescriptor_PropertyDocumentationData
{
get
@ -374,9 +422,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var mockPropertyInfo = new Mock<PropertyInfo>();
mockPropertyInfo.Setup(propertyInfo => propertyInfo.DeclaringType).Returns(tagHelperType);
mockPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns(propertyName);
var factory = new TagHelperDesignTimeDescriptorFactory();
// Act
var designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
var designTimeDescriptor = factory.CreateAttributeDescriptor(
mockPropertyInfo.Object);
// Assert
@ -456,11 +505,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
.Setup(propertyInfo => propertyInfo.Name)
.Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
TagHelperAttributeDesignTimeDescriptor designTimeDescriptor;
var factory = new TagHelperDesignTimeDescriptorFactory();
// Act
using (new CultureReplacer(culture))
{
designTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(
designTimeDescriptor = factory.CreateAttributeDescriptor(
mockPropertyInfo.Object);
}
@ -471,6 +521,50 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
TagHelperAttributeDesignTimeDescriptorComparer.Default);
}
[Fact]
public void CreateDescriptor_WithLocalizedProperty_CachesBasedOnCulture()
{
// Arrange
var tagHelperType = CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null);
var mockPropertyInfo = new Mock<PropertyInfo>();
mockPropertyInfo.Setup(propertyInfo => propertyInfo.DeclaringType).Returns(tagHelperType);
mockPropertyInfo
.Setup(propertyInfo => propertyInfo.Name)
.Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
var factory = new TagHelperDesignTimeDescriptorFactory();
var expectedFRDesignTimeDescriptor = new TagHelperAttributeDesignTimeDescriptor
{
Summary = "fr-FR: " + PropertyWithSummaryAndRemarks_Summary,
Remarks = "fr-FR: " + PropertyWithSummaryAndRemarks_Remarks
};
var expectedNLBEDesignTimeDescriptor = new TagHelperAttributeDesignTimeDescriptor
{
Summary = "nl-BE: " + PropertyWithSummaryAndRemarks_Summary,
Remarks = "nl-BE: " + PropertyWithSummaryAndRemarks_Remarks
};
TagHelperAttributeDesignTimeDescriptor frDesignTimeDescriptor, nlBEDesignTimeDescriptor;
// Act
using (new CultureReplacer("fr-FR"))
{
frDesignTimeDescriptor = factory.CreateAttributeDescriptor(mockPropertyInfo.Object);
}
using (new CultureReplacer("nl-BE"))
{
nlBEDesignTimeDescriptor = factory.CreateAttributeDescriptor(mockPropertyInfo.Object);
}
// Assert
Assert.Equal(
expectedFRDesignTimeDescriptor,
frDesignTimeDescriptor,
TagHelperAttributeDesignTimeDescriptorComparer.Default);
Assert.Equal(
expectedNLBEDesignTimeDescriptor,
nlBEDesignTimeDescriptor,
TagHelperAttributeDesignTimeDescriptorComparer.Default);
}
private static Type CreateDocumentationTagHelperType(string location, string codeBase)
{
return CreateType<DocumentedTagHelper>(location, codeBase);

View File

@ -11,10 +11,6 @@
"type": "build"
},
"Microsoft.AspNet.Testing": "1.0.0-*",
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"type": "build",
"version": "1.0.0-*"
},
"Microsoft.Extensions.WebEncoders": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
},
@ -27,6 +23,13 @@
"Moq": "4.2.1312.1622"
}
},
"dnxcore50": {}
"dnxcore50": {
"dependencies": {
"Microsoft.Extensions.HashCodeCombiner.Sources": {
"type": "build",
"version": "1.0.0-*"
}
}
}
}
}