diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IMemberInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IMemberInfo.cs
new file mode 100644
index 0000000000..6d569b0df1
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IMemberInfo.cs
@@ -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 System;
+using System.Collections.Generic;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ ///
+ /// Metadata common to types and properties.
+ ///
+ public interface IMemberInfo
+ {
+ ///
+ /// Gets the name.
+ ///
+ string Name { get; }
+
+ ///
+ /// Retrieves a collection of custom s of type applied
+ /// to this instance of .
+ ///
+ /// The type of to search for.
+ /// A sequence of custom s of type
+ /// .
+ /// Result not include inherited s.
+ IEnumerable GetCustomAttributes()
+ where TAttribute : Attribute;
+ }
+}
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IPropertyInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IPropertyInfo.cs
new file mode 100644
index 0000000000..beb0840b57
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/IPropertyInfo.cs
@@ -0,0 +1,26 @@
+// 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.
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ ///
+ /// Contains property metadata.
+ ///
+ public interface IPropertyInfo : IMemberInfo
+ {
+ ///
+ /// Gets a value indicating whether this property has a public getter.
+ ///
+ bool HasPublicGetter { get; }
+
+ ///
+ /// Gets a value indicating whether this property has a public setter.
+ ///
+ bool HasPublicSetter { get; }
+
+ ///
+ /// Gets the of the property.
+ ///
+ ITypeInfo PropertyType { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/ITypeInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/ITypeInfo.cs
new file mode 100644
index 0000000000..294f247932
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/ITypeInfo.cs
@@ -0,0 +1,61 @@
+// 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 System.Collections.Generic;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ ///
+ /// Contains type metadata.
+ ///
+ public interface ITypeInfo : IMemberInfo
+ {
+ ///
+ /// Fully qualified name of the type.
+ ///
+ string FullName { get; }
+
+ ///
+ /// Gets s for all properties of the current type excluding indexers.
+ ///
+ ///
+ /// Indexers in this context refer to the CLR notion of an indexer (this [string name]
+ /// and does not overlap with the semantics of
+ /// .
+ ///
+ IEnumerable Properties { get; }
+
+ ///
+ /// Gets a value indicating whether the type is public.
+ ///
+ bool IsPublic { get; }
+
+ ///
+ /// Gets a value indicating whether the type is abstract or an interface.
+ ///
+ bool IsAbstract { get; }
+
+ ///
+ /// Gets a value indicating whether the type is generic.
+ ///
+ bool IsGenericType { get; }
+
+ ///
+ /// Gets a value indicating whether the type implements the interface.
+ ///
+ bool IsTagHelper { get; }
+
+ ///
+ /// Gets the full names of the parameter types if the type implements
+ /// .
+ ///
+ ///
+ /// The full type names () of TKey and TValue
+ /// parameters if the type implements , otherwise null.
+ ///
+ ///
+ /// For open generic types, full type names for generic type parameters is null.
+ ///
+ string[] GetGenericDictionaryParameterNames();
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimePropertyInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimePropertyInfo.cs
new file mode 100644
index 0000000000..b79ff696d7
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimePropertyInfo.cs
@@ -0,0 +1,51 @@
+// 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 System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.AspNet.Razor.Runtime.TagHelpers;
+using Microsoft.Framework.Internal;
+
+namespace Microsoft.AspNet.Razor.Runtime
+{
+ ///
+ /// adapter for instances.
+ ///
+ public class RuntimePropertyInfo : IPropertyInfo
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The instance to adapt.
+ public RuntimePropertyInfo([NotNull] PropertyInfo propertyInfo)
+ {
+ Property = propertyInfo;
+ }
+
+ ///
+ /// The instance.
+ ///
+ public PropertyInfo Property { get; }
+
+ ///
+ public bool HasPublicGetter => Property.GetMethod != null && Property.GetMethod.IsPublic;
+
+ ///
+ public bool HasPublicSetter => Property.SetMethod != null && Property.SetMethod.IsPublic;
+
+ ///
+ public string Name => Property.Name;
+
+ ///
+ public ITypeInfo PropertyType => new RuntimeTypeInfo(Property.PropertyType.GetTypeInfo());
+
+ ///
+ public IEnumerable GetCustomAttributes() where TAttribute : Attribute
+ => Property.GetCustomAttributes(inherit: false);
+
+ ///
+ public override string ToString() =>
+ Property.ToString();
+ }
+}
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimeTypeInfo.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimeTypeInfo.cs
new file mode 100644
index 0000000000..dff34999c0
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/RuntimeTypeInfo.cs
@@ -0,0 +1,88 @@
+// 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Framework.Internal;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ ///
+ /// adapter for instances.
+ ///
+ public class RuntimeTypeInfo : ITypeInfo
+ {
+ private static readonly TypeInfo TagHelperTypeInfo = typeof(ITagHelper).GetTypeInfo();
+ private IEnumerable _properties;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// The instance to adapt.
+ public RuntimeTypeInfo([NotNull] TypeInfo typeInfo)
+ {
+ TypeInfo = typeInfo;
+ }
+
+ ///
+ /// The instance.
+ ///
+ public TypeInfo TypeInfo { get; }
+
+ ///
+ public string Name => TypeInfo.Name;
+
+ ///
+ public string FullName => TypeInfo.FullName;
+
+ ///
+ public bool IsAbstract => TypeInfo.IsAbstract;
+
+ ///
+ public bool IsGenericType => TypeInfo.IsGenericType;
+
+ ///
+ public bool IsPublic => TypeInfo.IsPublic;
+
+ ///
+ public IEnumerable Properties
+ {
+ get
+ {
+ if (_properties == null)
+ {
+ _properties = TypeInfo
+ .AsType()
+ .GetRuntimeProperties()
+ .Where(property => property.GetIndexParameters().Length == 0)
+ .Select(property => new RuntimePropertyInfo(property));
+ }
+
+ return _properties;
+ }
+ }
+
+ ///
+ public bool IsTagHelper => TagHelperTypeInfo.IsAssignableFrom(TypeInfo);
+
+ ///
+ public IEnumerable GetCustomAttributes() where TAttribute : Attribute =>
+ TypeInfo.GetCustomAttributes(inherit: false);
+
+ ///
+ public string[] GetGenericDictionaryParameterNames()
+ {
+ return ClosedGenericMatcher.ExtractGenericInterface(
+ TypeInfo.AsType(),
+ typeof(IDictionary<,>))
+ ?.GenericTypeArguments
+ .Select(type => type.FullName)
+ .ToArray();
+ }
+
+ ///
+ public override string ToString() => TypeInfo.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorFactory.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorFactory.cs
index 25195ddbff..c337ca89fc 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorFactory.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorFactory.cs
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
-using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Framework.Internal;
@@ -13,7 +12,7 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
///
- /// Factory for s from s.
+ /// Factory for s from s.
///
public static class TagHelperDescriptorFactory
{
@@ -35,31 +34,30 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
new[] { '@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*' });
///
- /// Creates a from the given .
+ /// Creates a from the given .
///
/// The assembly name that contains .
- /// The type to create a from.
+ /// The to create a from.
+ ///
/// Indicates if the returned s should include
/// design time specific information.
/// The used to collect s encountered
- /// when creating s for the given .
+ /// when creating s for the given .
///
- /// A collection of s that describe the given .
+ /// A collection of s that describe the given .
///
public static IEnumerable CreateDescriptors(
string assemblyName,
- [NotNull] Type type,
+ [NotNull] ITypeInfo typeInfo,
bool designTime,
[NotNull] ErrorSink errorSink)
{
- var typeInfo = type.GetTypeInfo();
-
if (ShouldSkipDescriptorCreation(designTime, typeInfo))
{
return Enumerable.Empty();
}
- var attributeDescriptors = GetAttributeDescriptors(type, designTime, errorSink);
+ var attributeDescriptors = GetAttributeDescriptors(typeInfo, designTime, errorSink);
var targetElementAttributes = GetValidTargetElementAttributes(typeInfo, errorSink);
var allowedChildren = GetAllowedChildren(typeInfo, errorSink);
@@ -76,16 +74,16 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
private static IEnumerable GetValidTargetElementAttributes(
- TypeInfo typeInfo,
+ ITypeInfo typeInfo,
ErrorSink errorSink)
{
- var targetElementAttributes = typeInfo.GetCustomAttributes(inherit: false);
+ var targetElementAttributes = typeInfo.GetCustomAttributes();
return targetElementAttributes.Where(attribute => ValidTargetElementAttributeNames(attribute, errorSink));
}
private static IEnumerable BuildTagHelperDescriptors(
- TypeInfo typeInfo,
+ ITypeInfo typeInfo,
string assemblyName,
IEnumerable attributeDescriptors,
IEnumerable targetElementAttributes,
@@ -97,7 +95,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
#if !DNXCORE50
if (designTime)
{
- typeDesignTimeDescriptor = TagHelperDesignTimeDescriptorFactory.CreateDescriptor(typeInfo.AsType());
+ var runtimeTypeInfo = typeInfo as RuntimeTypeInfo;
+ if (runtimeTypeInfo != null)
+ {
+ typeDesignTimeDescriptor =
+ TagHelperDesignTimeDescriptorFactory.CreateDescriptor(runtimeTypeInfo.TypeInfo.AsType());
+ }
}
#endif
@@ -138,9 +141,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeDesignTimeDescriptor));
}
- private static IEnumerable GetAllowedChildren(TypeInfo typeInfo, ErrorSink errorSink)
+ private static IEnumerable GetAllowedChildren(ITypeInfo typeInfo, ErrorSink errorSink)
{
- var restrictChildrenAttribute = typeInfo.GetCustomAttribute(inherit: false);
+ var restrictChildrenAttribute = typeInfo
+ .GetCustomAttributes()
+ .FirstOrDefault();
if (restrictChildrenAttribute == null)
{
return null;
@@ -338,7 +343,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
private static IEnumerable GetAttributeDescriptors(
- Type type,
+ ITypeInfo type,
bool designTime,
ErrorSink errorSink)
{
@@ -347,7 +352,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Keep indexer descriptors separate to avoid sorting the combined list later.
var indexerDescriptors = new List();
- var accessibleProperties = type.GetRuntimeProperties().Where(IsAccessibleProperty);
+ var accessibleProperties = type.Properties.Where(IsAccessibleProperty);
foreach (var property in accessibleProperties)
{
if (ShouldSkipDescriptorCreation(designTime, property))
@@ -355,13 +360,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
continue;
}
- var attributeNameAttribute = property.GetCustomAttribute(inherit: false);
+ var attributeNameAttribute = property
+ .GetCustomAttributes()
+ .FirstOrDefault();
var hasExplicitName =
attributeNameAttribute != null && !string.IsNullOrEmpty(attributeNameAttribute.Name);
var attributeName = hasExplicitName ? attributeNameAttribute.Name : ToHtmlCase(property.Name);
TagHelperAttributeDescriptor mainDescriptor = null;
- if (property.SetMethod?.IsPublic == true)
+ if (property.HasPublicSetter)
{
mainDescriptor = ToAttributeDescriptor(property, attributeName, designTime);
if (!ValidateTagHelperAttributeDescriptor(mainDescriptor, type, errorSink))
@@ -425,7 +432,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Internal for testing.
internal static bool ValidateTagHelperAttributeDescriptor(
TagHelperAttributeDescriptor attributeDescriptor,
- Type parentType,
+ ITypeInfo parentType,
ErrorSink errorSink)
{
string nameOrPrefix;
@@ -457,13 +464,16 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameOrPrefix);
}
- private static bool ShouldSkipDescriptorCreation(bool designTime, MemberInfo memberInfo)
+ private static bool ShouldSkipDescriptorCreation(bool designTime, IMemberInfo memberInfo)
{
if (designTime)
{
- var editorBrowsableAttribute = memberInfo.GetCustomAttribute(inherit: false);
+ var editorBrowsableAttribute = memberInfo
+ .GetCustomAttributes()
+ .FirstOrDefault();
- return editorBrowsableAttribute != null && editorBrowsableAttribute.State == EditorBrowsableState.Never;
+ return editorBrowsableAttribute != null &&
+ editorBrowsableAttribute.State == EditorBrowsableState.Never;
}
return false;
@@ -471,7 +481,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private static bool ValidateTagHelperAttributeNameOrPrefix(
string attributeNameOrPrefix,
- Type parentType,
+ ITypeInfo parentType,
string propertyName,
ErrorSink errorSink,
string nameOrPrefix)
@@ -540,7 +550,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
private static TagHelperAttributeDescriptor ToAttributeDescriptor(
- PropertyInfo property,
+ IPropertyInfo property,
string attributeName,
bool designTime)
{
@@ -553,21 +563,18 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
private static TagHelperAttributeDescriptor ToIndexerAttributeDescriptor(
- PropertyInfo property,
+ IPropertyInfo property,
HtmlAttributeNameAttribute attributeNameAttribute,
- Type parentType,
+ ITypeInfo parentType,
ErrorSink errorSink,
string defaultPrefix,
bool designTime,
out bool isInvalid)
{
isInvalid = false;
- var hasPublicSetter = property.SetMethod?.IsPublic == true;
- var dictionaryTypeArguments = ClosedGenericMatcher.ExtractGenericInterface(
- property.PropertyType,
- typeof(IDictionary<,>))
- ?.GenericTypeArguments;
- if (dictionaryTypeArguments?[0] != typeof(string))
+ var hasPublicSetter = property.HasPublicSetter;
+ var dictionaryTypeArguments = property.PropertyType.GetGenericDictionaryParameterNames();
+ if (dictionaryTypeArguments?[0] != typeof(string).FullName)
{
if (attributeNameAttribute?.DictionaryAttributePrefix != null)
{
@@ -634,13 +641,13 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return ToAttributeDescriptor(
property,
attributeName: prefix,
- typeName: dictionaryTypeArguments[1].FullName,
+ typeName: dictionaryTypeArguments[1],
isIndexer: true,
designTime: designTime);
}
private static TagHelperAttributeDescriptor ToAttributeDescriptor(
- PropertyInfo property,
+ IPropertyInfo property,
string attributeName,
string typeName,
bool isIndexer,
@@ -651,8 +658,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
#if !DNXCORE50
if (designTime)
{
- propertyDesignTimeDescriptor =
- TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(property);
+ var runtimeProperty = property as RuntimePropertyInfo;
+ if (runtimeProperty != null)
+ {
+ propertyDesignTimeDescriptor =
+ TagHelperDesignTimeDescriptorFactory.CreateAttributeDescriptor(runtimeProperty.Property);
+ }
}
#endif
@@ -666,11 +677,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
};
}
- private static bool IsAccessibleProperty(PropertyInfo property)
+ private static bool IsAccessibleProperty(IPropertyInfo property)
{
// Accessible properties are those with public getters and without [HtmlAttributeNotBound].
- return property.GetMethod?.IsPublic == true &&
- property.GetCustomAttribute(inherit: false) == null;
+ return property.HasPublicGetter &&
+ property.GetCustomAttributes().FirstOrDefault() == null;
}
///
diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs
index bc383d41ac..8a5ea0b43d 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperTypeResolver.cs
@@ -17,25 +17,16 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private static readonly TypeInfo ITagHelperTypeInfo = typeof(ITagHelper).GetTypeInfo();
///
- /// Instantiates a new instance of the class.
- ///
- public TagHelperTypeResolver()
- {
- }
-
- ///
- /// Loads an using the given and resolves
- /// all valid s.
+ /// Locates valid types from the named .
///
/// The name of an to search.
/// The of the associated
/// responsible for the current call.
///
/// The used to record errors found when resolving
- /// s.
- /// An of valid s.
- ///
- public IEnumerable Resolve(
+ /// types.
+ /// An of valid types.
+ public IEnumerable Resolve(
string name,
SourceLocation documentLocation,
[NotNull] ErrorSink errorSink)
@@ -48,15 +39,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Resources.TagHelperTypeResolver_TagHelperAssemblyNameCannotBeEmptyOrNull,
errorLength);
- return Type.EmptyTypes;
+ return Enumerable.Empty();
}
var assemblyName = new AssemblyName(name);
- IEnumerable libraryTypes;
+ IEnumerable libraryTypes;
try
{
- libraryTypes = GetExportedTypes(assemblyName);
+ libraryTypes = GetTopLevelExportedTypes(assemblyName);
}
catch (Exception ex)
{
@@ -67,13 +58,26 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
ex.Message),
name.Length);
- return Type.EmptyTypes;
+ return Enumerable.Empty();
}
- var validTagHelpers = libraryTypes.Where(IsTagHelper);
+ return libraryTypes.Where(IsTagHelper);
+ }
- // Convert from TypeInfo[] to Type[]
- return validTagHelpers.Select(type => type.AsType());
+ ///
+ /// Returns all non-nested exported types from the given
+ ///
+ /// The to get s from.
+ ///
+ /// An of types exported from the given .
+ ///
+ protected virtual IEnumerable GetTopLevelExportedTypes([NotNull] AssemblyName assemblyName)
+ {
+ var exportedTypeInfos = GetExportedTypes(assemblyName);
+
+ return exportedTypeInfos
+ .Where(typeInfo => !typeInfo.IsNested)
+ .Select(typeInfo => new RuntimeTypeInfo(typeInfo));
}
///
@@ -91,13 +95,12 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
// Internal for testing.
- internal virtual bool IsTagHelper(TypeInfo typeInfo)
+ internal virtual bool IsTagHelper(ITypeInfo typeInfo)
{
return typeInfo.IsPublic &&
!typeInfo.IsAbstract &&
!typeInfo.IsGenericType &&
- !typeInfo.IsNested &&
- ITagHelperTypeInfo.IsAssignableFrom(typeInfo);
+ typeInfo.IsTagHelper;
}
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DoesNotImplementRealITagHelper.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DoesNotImplementRealITagHelper.cs
new file mode 100644
index 0000000000..b1ed2ee105
--- /dev/null
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/DoesNotImplementRealITagHelper.cs
@@ -0,0 +1,9 @@
+// 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.
+
+namespace Microsoft.AspNet.Razor.Fake
+{
+ public class DoesNotImplementRealITagHelper : Microsoft.AspNet.Razor.Fake.ITagHelper
+ {
+ }
+}
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/IFakeTagHelper.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/IFakeTagHelper.cs
new file mode 100644
index 0000000000..1e9ef72e21
--- /dev/null
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/IFakeTagHelper.cs
@@ -0,0 +1,14 @@
+// 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 System;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Razor.Runtime.TagHelpers;
+
+namespace Microsoft.AspNet.Razor.Fake
+{
+ public interface ITagHelper
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/ImplementsRealTagHelper.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/ImplementsRealTagHelper.cs
new file mode 100644
index 0000000000..b7d3a21a54
--- /dev/null
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/ImplementsRealTagHelper.cs
@@ -0,0 +1,26 @@
+// 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 System;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Razor.Runtime.TagHelpers;
+
+namespace Microsoft.AspNet.Razor.Fake
+{
+ public class ImplementsRealITagHelper : Microsoft.AspNet.Razor.Runtime.TagHelpers.ITagHelper
+ {
+ public int Order
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+}
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimePropertyInfoTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimePropertyInfoTest.cs
new file mode 100644
index 0000000000..78b1fb1cb7
--- /dev/null
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimePropertyInfoTest.cs
@@ -0,0 +1,159 @@
+// 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 System;
+using System.Linq;
+using System.Reflection;
+using Xunit;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ public class RuntimePropertyInfoTest
+ {
+ [Fact]
+ public void PropertyInfo_ReturnsMetadataOfAdaptingProperty()
+ {
+ // Arrange
+ var property = GetPropertyInfo(nameof(TestType.Property));
+ var runtimePropertyInfo = new RuntimePropertyInfo(property);
+
+ // Act
+ var actual = runtimePropertyInfo.Property;
+
+ // Assert
+ Assert.Same(property, actual);
+ var runtimeTypeInfo = Assert.IsType(runtimePropertyInfo.PropertyType);
+ Assert.Same(property.PropertyType, runtimeTypeInfo.TypeInfo);
+ }
+
+ [Theory]
+ [InlineData(nameof(TestType.Property))]
+ [InlineData(nameof(TestType.PrivateSetter))]
+ [InlineData(nameof(TestType.PropertyWithoutSetter))]
+ public void HasPublicGetter_ReturnsTrueIfGetterExistsAndIsPublic(string propertyName)
+ {
+ // Arrange
+ var property = GetPropertyInfo(propertyName);
+ var runtimePropertyInfo = new RuntimePropertyInfo(property);
+
+ // Act
+ var result = runtimePropertyInfo.HasPublicGetter;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Theory]
+ [InlineData(nameof(TestType.PrivateGetter))]
+ [InlineData(nameof(TestType.PropertyWithoutGetter))]
+ [InlineData("ProtectedProperty")]
+ public void HasPublicGetter_ReturnsFalseIfGetterDoesNotExistOrIsNonPublic(string propertyName)
+ {
+ // Arrange
+ var property = GetPropertyInfo(propertyName);
+ var runtimePropertyInfo = new RuntimePropertyInfo(property);
+
+ // Act
+ var result = runtimePropertyInfo.HasPublicGetter;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Theory]
+ [InlineData(nameof(TestType.Property))]
+ [InlineData(nameof(TestType.PrivateGetter))]
+ [InlineData(nameof(TestType.PropertyWithoutGetter))]
+ public void HasPublicSetter_ReturnsTrueIfSetterExistsAndIsPublic(string propertyName)
+ {
+ // Arrange
+ var property = GetPropertyInfo(propertyName);
+ var runtimePropertyInfo = new RuntimePropertyInfo(property);
+
+ // Act
+ var result = runtimePropertyInfo.HasPublicSetter;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Theory]
+ [InlineData(nameof(TestType.PrivateSetter))]
+ [InlineData(nameof(TestType.PropertyWithoutSetter))]
+ [InlineData("ProtectedProperty")]
+ public void HasPublicSetter_ReturnsFalseIfGetterDoesNotExistOrIsNonPublic(string propertyName)
+ {
+ // Arrange
+ var property = GetPropertyInfo(propertyName);
+ var runtimePropertyInfo = new RuntimePropertyInfo(property);
+
+ // Act
+ var result = runtimePropertyInfo.HasPublicSetter;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Fact]
+ public void GetAttributes_ReturnsCustomAttributesOfSpecifiedType()
+ {
+ // Arrange
+ var property = GetPropertyInfo(nameof(TestType.PropertyWithAttributes));
+ var runtimeProperty = new RuntimePropertyInfo(property);
+
+ // Act
+ var attributes = property.GetCustomAttributes();
+
+ // Assert
+ var htmlAttributeName = Assert.Single(attributes);
+ Assert.Equal("somename", htmlAttributeName.Name);
+ }
+
+ [Fact]
+ public void GetAttributes_DoesNotInheritAttributes()
+ {
+ // Arrange
+ var property = GetPropertyInfo(nameof(TestType.PropertyWithAttributes));
+ var runtimeProperty = new RuntimePropertyInfo(property);
+
+ // Act
+ var attributes = property.GetCustomAttributes();
+
+ // Assert
+ Assert.Empty(attributes);
+ }
+
+ private static PropertyInfo GetPropertyInfo(string propertyName)
+ {
+ return typeof(TestType).GetRuntimeProperties()
+ .FirstOrDefault(p => p.Name == propertyName);
+ }
+
+ public class BaseType
+ {
+ [HtmlAttributeNotBound]
+ public virtual string PropertyWithAttributes { get; }
+ }
+
+ public class TestType : BaseType
+ {
+ public string Property { get; set; }
+
+ public int PrivateSetter { get; private set; }
+
+ public object PrivateGetter { private get; set; }
+
+ protected DateTimeOffset ProtectedProperty { get; set; }
+
+ public string PropertyWithoutGetter
+ {
+ set { }
+ }
+
+ public int PropertyWithoutSetter => 0;
+
+ [HtmlAttributeName("somename")]
+ public override string PropertyWithAttributes { get; }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimeTypeInfoTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimeTypeInfoTest.cs
new file mode 100644
index 0000000000..8c4a3290e0
--- /dev/null
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/RuntimeTypeInfoTest.cs
@@ -0,0 +1,375 @@
+// 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 System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Razor.Runtime.TagHelpers;
+using Xunit;
+
+namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
+{
+ public class RuntimeTypeInfoTest
+ {
+ [Theory]
+ [InlineData(typeof(int))]
+ [InlineData(typeof(string))]
+ [InlineData(typeof(Tuple<,>))]
+ [InlineData(typeof(IDictionary))]
+ [InlineData(typeof(IDictionary>))]
+ [InlineData(typeof(AbstractType))]
+ [InlineData(typeof(PrivateType))]
+ [InlineData(typeof(KnownKeyDictionary<>))]
+ [InlineData(typeof(KnownKeyDictionary))]
+ public void RuntimeTypeInfo_ReturnsMetadataOfAdaptingType(Type type)
+ {
+ // Arrange
+ var typeInfo = type.GetTypeInfo();
+ var runtimeTypeInfo = new RuntimeTypeInfo(typeInfo);
+
+ // Act and Assert
+ Assert.Same(runtimeTypeInfo.TypeInfo, typeInfo);
+ Assert.Equal(runtimeTypeInfo.Name, typeInfo.Name);
+ Assert.Equal(runtimeTypeInfo.FullName, typeInfo.FullName);
+ Assert.Equal(runtimeTypeInfo.IsAbstract, typeInfo.IsAbstract);
+ Assert.Equal(runtimeTypeInfo.IsGenericType, typeInfo.IsGenericType);
+ Assert.Equal(runtimeTypeInfo.IsPublic, typeInfo.IsPublic);
+ }
+
+ [Fact]
+ public void Properties_ReturnsPublicPropertiesOfAdaptingType()
+ {
+ // Arrange
+ var typeInfo = typeof(SubType).GetTypeInfo();
+ var runtimeTypeInfo = new RuntimeTypeInfo(typeInfo);
+
+ // Act and Assert
+ Assert.Collection(runtimeTypeInfo.Properties,
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("Property1", property.Name);
+ },
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("Property2", property.Name);
+ },
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("Property3", property.Name);
+ },
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("Property4", property.Name);
+ },
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("BaseTypeProperty", property.Name);
+ },
+ property =>
+ {
+ Assert.IsType(property);
+ Assert.Equal("ProtectedProperty", property.Name);
+ });
+ }
+
+ [Fact]
+ public void GetCustomAttributes_ReturnsAllAttributesOfType()
+ {
+ // Arrange
+ var typeInfo = typeof(TypeWithAttributes).GetTypeInfo();
+ var runtimeTypeInfo = new RuntimeTypeInfo(typeInfo);
+ var expected = typeInfo.GetCustomAttributes();
+
+ // Act
+ var actual = runtimeTypeInfo.GetCustomAttributes();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Fact]
+ public void GetCustomAttributes_DoesNotInheritAttributesFromBaseType()
+ {
+ // Arrange
+ var typeInfo = typeof(SubType).GetTypeInfo();
+ var runtimeTypeInfo = new RuntimeTypeInfo(typeInfo);
+
+ // Act
+ var actual = runtimeTypeInfo.GetCustomAttributes();
+
+ // Assert
+ Assert.Empty(actual);
+ }
+
+ [Theory]
+ [InlineData(typeof(ITagHelper))]
+ [InlineData(typeof(TagHelper))]
+ [InlineData(typeof(ImplementsITagHelper))]
+ [InlineData(typeof(DerivesFromTagHelper))]
+ [InlineData(typeof(Fake.ImplementsRealITagHelper))]
+ public void IsTagHelper_ReturnsTrueIfTypeImplementsTagHelper(Type type)
+ {
+ // Arrange
+ var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo());
+
+ // Act
+ var result = runtimeTypeInfo.IsTagHelper;
+
+ // Assert
+ Assert.True(result);
+ }
+
+ [Theory]
+ [InlineData(typeof(string))]
+ [InlineData(typeof(SubType))]
+ [InlineData(typeof(Fake.DoesNotImplementRealITagHelper))]
+ public void IsTagHelper_ReturnsFalseIfTypeDoesNotImplementTagHelper(Type type)
+ {
+ // Arrange
+ var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo());
+
+ // Act
+ var result = runtimeTypeInfo.IsTagHelper;
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Theory]
+ [InlineData(typeof(Dictionary), new[] { typeof(string), typeof(string) })]
+ [InlineData(typeof(DerivesFromDictionary), new[] { typeof(int), typeof(object) })]
+ [InlineData(typeof(ImplementsIDictionary), new[] { typeof(List), typeof(string) })]
+ [InlineData(typeof(IDictionary>),
+ new[] { typeof(string), typeof(IDictionary) })]
+ [InlineData(typeof(Dictionary<,>), new Type[] { null, null })]
+ [InlineData(typeof(KnownKeyDictionary<>), new[] { typeof(string), null })]
+ [InlineData(typeof(KnownKeyDictionary),
+ new[] { typeof(string), typeof(ImplementsIDictionary) })]
+ public void GetGenericDictionaryParameterNames_ReturnsKeyAndValueParameterTypeNames(
+ Type type,
+ Type[] expectedTypes)
+ {
+ // Arrange
+ var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo());
+ var expected = expectedTypes.Select(t => t?.FullName);
+
+ // Act
+ var actual = runtimeTypeInfo.GetGenericDictionaryParameterNames();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineData(typeof(int))]
+ [InlineData(typeof(string))]
+ [InlineData(typeof(List))]
+ [InlineData(typeof(IDictionary))]
+ [InlineData(typeof(ITagHelper))]
+ public void GetGenericDictionaryParameterNames_ReturnsNullIfTypeDoesNotImplementGenericDictionary(Type type)
+ {
+ // Arrange
+ var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo());
+
+ // Act
+ var actual = runtimeTypeInfo.GetGenericDictionaryParameterNames();
+
+ // Assert
+ Assert.Null(actual);
+ }
+
+ public class AbstractType
+ {
+ }
+
+ internal class InternalType
+ {
+ }
+
+ private class PrivateType
+ {
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ private class BaseType
+ {
+ public string this[string key]
+ {
+ get { return ""; }
+ set { }
+ }
+
+ public string BaseTypeProperty { get; set; }
+
+ protected int ProtectedProperty { get; set; }
+ }
+
+ private class SubType : BaseType
+ {
+ public string Property1 { get; set; }
+
+ public int Property2 { get; }
+
+ public object Property3 { private get; set; }
+
+ private int Property4 { get; set; }
+ }
+
+ [TargetElement("test1")]
+ [TargetElement("test2")]
+ private class TypeWithAttributes
+ {
+ }
+
+ private class DerivesFromTagHelper : TagHelper
+ {
+ }
+
+ private class ImplementsITagHelper : ITagHelper
+ {
+ public int Order { get; } = 0;
+
+ public Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ private class DerivesFromDictionary : Dictionary
+ {
+ }
+
+ private class ImplementsIDictionary : IDictionary, string>, IReadOnlyList
+ {
+ public int this[int index]
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public string this[List key]
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+
+ set
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public ICollection> Keys
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public ICollection Values
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public void Add(KeyValuePair, string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(List key, string value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Contains(KeyValuePair, string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool ContainsKey(List key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void CopyTo(KeyValuePair, string>[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IEnumerator, string>> GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(KeyValuePair, string> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(List key)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool TryGetValue(List key, out string value)
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class KnownKeyDictionary : Dictionary
+ {
+ }
+
+ private class CustomType
+ {
+ }
+ }
+}
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorFactoryTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorFactoryTest.cs
index db99a15e0b..95009711be 100644
--- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorFactoryTest.cs
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorFactoryTest.cs
@@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
@@ -175,7 +175,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
@@ -256,7 +256,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: true,
errorSink: errorSink);
@@ -493,7 +493,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime,
errorSink);
@@ -695,7 +695,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
@@ -744,7 +744,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
@@ -781,7 +781,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(OverriddenAttributeTagHelper),
+ GetTypeInfo(typeof(OverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -815,7 +815,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(InheritedOverriddenAttributeTagHelper),
+ GetTypeInfo(typeof(InheritedOverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -849,7 +849,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(InheritedNotOverriddenAttributeTagHelper),
+ GetTypeInfo(typeof(InheritedNotOverriddenAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -870,7 +870,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
objectAssemblyName,
- typeof(object),
+ GetTypeInfo(typeof(object)),
designTime: false,
errorSink: errorSink);
@@ -902,7 +902,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(InheritedSingleAttributeTagHelper),
+ GetTypeInfo(typeof(InheritedSingleAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -930,7 +930,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(SingleAttributeTagHelper),
+ GetTypeInfo(typeof(SingleAttributeTagHelper)),
designTime: false,
errorSink: new ErrorSink());
@@ -959,7 +959,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(MissingAccessorTagHelper),
+ GetTypeInfo(typeof(MissingAccessorTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -988,7 +988,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(NonPublicAccessorTagHelper),
+ GetTypeInfo(typeof(NonPublicAccessorTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1020,7 +1020,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(NotBoundAttributeTagHelper),
+ GetTypeInfo(typeof(NotBoundAttributeTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1039,7 +1039,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(DuplicateAttributeNameTagHelper),
+ GetTypeInfo(typeof(DuplicateAttributeNameTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1086,7 +1086,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(MultiTagTagHelper),
+ GetTypeInfo(typeof(MultiTagTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1118,7 +1118,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(InheritedMultiTagTagHelper),
+ GetTypeInfo(typeof(InheritedMultiTagTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1148,7 +1148,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(DuplicateTagNameTagHelper),
+ GetTypeInfo(typeof(DuplicateTagNameTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1178,7 +1178,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- typeof(OverrideNameTagHelper),
+ GetTypeInfo(typeof(OverrideNameTagHelper)),
designTime: false,
errorSink: errorSink);
@@ -1366,7 +1366,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- type,
+ GetTypeInfo(type),
designTime: false,
errorSink: errorSink);
@@ -1597,7 +1597,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
- tagHelperType,
+ GetTypeInfo(tagHelperType),
designTime: false,
errorSink: errorSink);
@@ -1651,7 +1651,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var result = TagHelperDescriptorFactory.ValidateTagHelperAttributeDescriptor(
descriptor,
- typeof(MultiTagTagHelper),
+ GetTypeInfo(typeof(MultiTagTagHelper)),
errorSink);
// Assert
@@ -1693,7 +1693,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var result = TagHelperDescriptorFactory.ValidateTagHelperAttributeDescriptor(
descriptor,
- typeof(MultiTagTagHelper),
+ GetTypeInfo(typeof(MultiTagTagHelper)),
errorSink);
// Assert
@@ -1739,7 +1739,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var result = TagHelperDescriptorFactory.ValidateTagHelperAttributeDescriptor(
descriptor,
- typeof(MultiTagTagHelper),
+ GetTypeInfo(typeof(MultiTagTagHelper)),
errorSink);
// Assert
@@ -1794,7 +1794,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var result = TagHelperDescriptorFactory.ValidateTagHelperAttributeDescriptor(
descriptor,
- typeof(MultiTagTagHelper),
+ GetTypeInfo(typeof(MultiTagTagHelper)),
errorSink);
// Assert
@@ -2101,6 +2101,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
};
}
+ private static ITypeInfo GetTypeInfo(Type tagHelperType) =>
+ new RuntimeTypeInfo(tagHelperType.GetTypeInfo());
+
[RestrictChildren("p")]
private class RestrictChildrenTagHelper
{
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorResolverTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorResolverTest.cs
index 4482690b2d..8973f5a39a 100644
--- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorResolverTest.cs
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperDescriptorResolverTest.cs
@@ -1575,7 +1575,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return types?.Select(type => type.GetTypeInfo()) ?? Enumerable.Empty();
}
- internal override bool IsTagHelper(TypeInfo typeInfo)
+ internal override bool IsTagHelper(ITypeInfo typeInfo)
{
return true;
}
diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs
index 0ccf0daf79..d72266253f 100644
--- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs
+++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs
@@ -62,7 +62,17 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var types = tagHelperTypeResolver.Resolve("Foo", SourceLocation.Zero, new ErrorSink());
// Assert
- Assert.Equal(ValidTestableTagHelpers, types);
+ Assert.Collection(types,
+ type =>
+ {
+ var typeInfo = Assert.IsType(type);
+ Assert.Equal(typeof(Valid_PlainTagHelper).GetTypeInfo(), typeInfo.TypeInfo);
+ },
+ type =>
+ {
+ var typeInfo = Assert.IsType(type);
+ Assert.Equal(typeof(Valid_InheritedTagHelper).GetTypeInfo(), typeInfo.TypeInfo);
+ });
}
[Fact]