Change ITypeInfo.IsTagHelper to ITypeInfo.ImplementsInterface(ITypeInfo)

Fixes #511
This commit is contained in:
Pranav K 2015-09-25 15:05:39 -07:00
parent d2a7a355cc
commit e87f10e8f8
13 changed files with 335 additions and 131 deletions

View File

@ -18,13 +18,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
[DebuggerDisplay("{Name}")] [DebuggerDisplay("{Name}")]
public class CodeAnalysisSymbolBasedTypeInfo : ITypeInfo public class CodeAnalysisSymbolBasedTypeInfo : ITypeInfo
{ {
/// <summary> private static readonly System.Reflection.TypeInfo OpenGenericDictionaryTypeInfo =
/// The <see cref="System.Reflection.TypeInfo"/> for <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static readonly System.Reflection.TypeInfo OpenGenericDictionaryTypeInfo =
typeof(IDictionary<,>).GetTypeInfo(); typeof(IDictionary<,>).GetTypeInfo();
private static readonly System.Reflection.TypeInfo TagHelperTypeInfo =
typeof(ITagHelper).GetTypeInfo();
private readonly ITypeSymbol _type; private readonly ITypeSymbol _type;
private readonly ITypeSymbol _underlyingType; private readonly ITypeSymbol _underlyingType;
private string _fullName; private string _fullName;
@ -120,13 +115,33 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
} }
/// <inheritdoc /> /// <inheritdoc />
public bool IsTagHelper public bool ImplementsInterface(ITypeInfo interfaceTypeInfo)
{ {
get if (interfaceTypeInfo == null)
{ {
return _type.AllInterfaces.Any( throw new ArgumentNullException(nameof(interfaceTypeInfo));
implementedInterface => IsType(implementedInterface, TagHelperTypeInfo));
} }
var runtimeTypeInfo = interfaceTypeInfo as RuntimeTypeInfo;
if (runtimeTypeInfo != null)
{
return runtimeTypeInfo.TypeInfo.IsInterface &&
_type.AllInterfaces.Any(implementedInterface => IsType(implementedInterface, runtimeTypeInfo.TypeInfo));
}
var codeAnalysisTypeInfo = interfaceTypeInfo as CodeAnalysisSymbolBasedTypeInfo;
if (codeAnalysisTypeInfo != null)
{
return codeAnalysisTypeInfo.TypeSymbol.TypeKind == TypeKind.Interface &&
_type.AllInterfaces.Any(
implementedInterface => implementedInterface == codeAnalysisTypeInfo.TypeSymbol);
}
throw new ArgumentException(
Resources.FormatArgumentMustBeAnInstanceOf(
typeof(RuntimeTypeInfo).FullName,
typeof(CodeAnalysisSymbolBasedTypeInfo).FullName),
nameof(interfaceTypeInfo));
} }
private string SanitizedFullName private string SanitizedFullName
@ -193,8 +208,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
System.Reflection.TypeInfo targetTypeInfo) System.Reflection.TypeInfo targetTypeInfo)
{ {
return string.Equals( return string.Equals(
targetTypeInfo.FullName, RuntimeTypeInfo.SanitizeFullName(targetTypeInfo.FullName),
GetFullName(sourceTypeSymbol), RuntimeTypeInfo.SanitizeFullName(GetFullName(sourceTypeSymbol)),
StringComparison.Ordinal); StringComparison.Ordinal);
} }

View File

@ -10,6 +10,22 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
private static readonly ResourceManager _resourceManager private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.AspNet.Razor.Runtime.Precompilation.Resources", typeof(Resources).GetTypeInfo().Assembly); = new ResourceManager("Microsoft.AspNet.Razor.Runtime.Precompilation.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// Argument must be an instance of '{0}' or '{1}'.
/// </summary>
internal static string ArgumentMustBeAnInstanceOf
{
get { return GetString("ArgumentMustBeAnInstanceOf"); }
}
/// <summary>
/// Argument must be an instance of '{0}' or '{1}'.
/// </summary>
internal static string FormatArgumentMustBeAnInstanceOf(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ArgumentMustBeAnInstanceOf"), p0, p1);
}
/// <summary> /// <summary>
/// Unable to find a suitable constructor for type '{0}'. /// Unable to find a suitable constructor for type '{0}'.
/// </summary> /// </summary>

View File

@ -117,6 +117,9 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="ArgumentMustBeAnInstanceOf" xml:space="preserve">
<value>Argument must be an instance of '{0}' or '{1}'.</value>
</data>
<data name="CodeAnalysisConstructorNotFound" xml:space="preserve"> <data name="CodeAnalysisConstructorNotFound" xml:space="preserve">
<value>Unable to find a suitable constructor for type '{0}'.</value> <value>Unable to find a suitable constructor for type '{0}'.</value>
</data> </data>

View File

@ -442,6 +442,22 @@ namespace Microsoft.AspNet.Razor.Runtime
return GetString("TagHelperDescriptorFactory_ParentTag"); return GetString("TagHelperDescriptorFactory_ParentTag");
} }
/// <summary>
/// Argument must be an instance of '{0}'.
/// </summary>
internal static string ArgumentMustBeAnInstanceOf
{
get { return GetString("ArgumentMustBeAnInstanceOf"); }
}
/// <summary>
/// Argument must be an instance of '{0}'.
/// </summary>
internal static string FormatArgumentMustBeAnInstanceOf(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ArgumentMustBeAnInstanceOf"), p0);
}
private static string GetString(string name, params string[] formatterNames) private static string GetString(string name, params string[] formatterNames)
{ {
var value = _resourceManager.GetString(name); var value = _resourceManager.GetString(name);

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader> <resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment> <comment>This is a comment</comment>
</data> </data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
@ -198,4 +198,7 @@
<data name="TagHelperDescriptorFactory_ParentTag" xml:space="preserve"> <data name="TagHelperDescriptorFactory_ParentTag" xml:space="preserve">
<value>Parent Tag</value> <value>Parent Tag</value>
</data> </data>
<data name="ArgumentMustBeAnInstanceOf" xml:space="preserve">
<value>Argument must be an instance of '{0}'.</value>
</data>
</root> </root>

View File

@ -49,9 +49,9 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
bool IsGenericType { get; } bool IsGenericType { get; }
/// <summary> /// <summary>
/// Gets a value indicating whether the type implements the <see cref="ITagHelper"/> interface. /// Gets a value indicating whether the type implements the <param name="interfaceTypeInfo"/> interface.
/// </summary> /// </summary>
bool IsTagHelper { get; } bool ImplementsInterface(ITypeInfo interfaceTypeInfo);
/// <summary> /// <summary>
/// Gets the <see cref="ITypeInfo[]"/> for the <c>TKey</c> and <c>TValue</c> parameters of /// Gets the <see cref="ITypeInfo[]"/> for the <c>TKey</c> and <c>TValue</c> parameters of

View File

@ -77,7 +77,23 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
} }
/// <inheritdoc /> /// <inheritdoc />
public bool IsTagHelper => TagHelperTypeInfo.IsAssignableFrom(TypeInfo); public bool ImplementsInterface(ITypeInfo interfaceTypeInfo)
{
if (interfaceTypeInfo == null)
{
throw new ArgumentNullException(nameof(interfaceTypeInfo));
}
var runtimeTypeInfo = interfaceTypeInfo as RuntimeTypeInfo;
if (runtimeTypeInfo == null)
{
throw new ArgumentException(
Resources.FormatArgumentMustBeAnInstanceOf(typeof(RuntimeTypeInfo).FullName),
nameof(interfaceTypeInfo));
}
return runtimeTypeInfo.TypeInfo.IsInterface && runtimeTypeInfo.TypeInfo.IsAssignableFrom(TypeInfo);
}
private string SanitizedFullName private string SanitizedFullName
{ {

View File

@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
/// </summary> /// </summary>
public class TagHelperTypeResolver public class TagHelperTypeResolver
{ {
private static readonly TypeInfo ITagHelperTypeInfo = typeof(ITagHelper).GetTypeInfo(); private static readonly ITypeInfo ITagHelperTypeInfo = new RuntimeTypeInfo(typeof(ITagHelper).GetTypeInfo());
/// <summary> /// <summary>
/// Locates valid <see cref="ITagHelper"/> types from the <see cref="Assembly"/> named <paramref name="name"/>. /// Locates valid <see cref="ITagHelper"/> types from the <see cref="Assembly"/> named <paramref name="name"/>.
@ -109,7 +109,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
return typeInfo.IsPublic && return typeInfo.IsPublic &&
!typeInfo.IsAbstract && !typeInfo.IsAbstract &&
!typeInfo.IsGenericType && !typeInfo.IsGenericType &&
typeInfo.IsTagHelper; typeInfo.ImplementsInterface(ITagHelperTypeInfo);
} }
} }
} }

View File

@ -0,0 +1,38 @@
// 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;
namespace Microsoft.AspNet.Razor.Runtime
{
public class DerivingFromIList : IReadOnlyList<string>
{
public string this[int index]
{
get
{
throw new NotImplementedException();
}
}
public int Count
{
get
{
throw new NotImplementedException();
}
}
public IEnumerator<string> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,11 @@
// 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
{
public class DerivingFromList : List<string>
{
}
}

View File

@ -8,6 +8,7 @@ using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Testing;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Xunit; using Xunit;
@ -15,7 +16,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{ {
public class PrecompilationTagHelperTypeResolverTest public class PrecompilationTagHelperTypeResolverTest
{ {
private static readonly TypeInfo TagHelperTypeInfo = typeof(ITagHelper).GetTypeInfo(); private static readonly ITypeInfo TagHelperTypeInfo = new RuntimeTypeInfo(typeof(ITagHelper).GetTypeInfo());
[Theory] [Theory]
[InlineData(typeof(TypeDerivingFromITagHelper))] [InlineData(typeof(TypeDerivingFromITagHelper))]
@ -35,6 +36,60 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
AssertEqual(expected, actual); AssertEqual(expected, actual);
} }
[Fact]
public void ImplementsInterface_ThrowsIfPassedInParameterIsNotRuntimeTypeOrCodeAnalysisBasedTypeInfo()
{
// Arrange
var interfaceType = new TestTypeInfo();
var compilation = CompilationUtility.GetCompilation(nameof(DerivingFromList));
var tagHelperResolver = new PrecompilationTagHelperTypeResolver(compilation);
// Act
var exportedTypes = tagHelperResolver.GetExportedTypes(compilation.AssemblyName);
// Assert
var actual = Assert.Single(exportedTypes);
ExceptionAssert.ThrowsArgument(() => actual.ImplementsInterface(interfaceType),
"interfaceTypeInfo",
$"Argument must be an instance of '{typeof(RuntimeTypeInfo)}' or '{typeof(CodeAnalysisSymbolBasedTypeInfo)}'.");
}
[Theory]
[InlineData(typeof(DerivingFromList))]
[InlineData(typeof(DerivingFromIList))]
public void ImplementsInterface_ReturnsTrueIfTypeDerivesFromInterface(Type expected)
{
// Arrange
var interfaceType = new RuntimeTypeInfo(typeof(IEnumerable<string>).GetTypeInfo());
var compilation = CompilationUtility.GetCompilation(expected.Name);
var tagHelperResolver = new PrecompilationTagHelperTypeResolver(compilation);
// Act
var exportedTypes = tagHelperResolver.GetExportedTypes(compilation.AssemblyName);
// Assert
var actual = Assert.Single(exportedTypes);
Assert.True(actual.ImplementsInterface(interfaceType));
}
[Theory]
[InlineData(typeof(TagHelper))]
[InlineData(typeof(IEnumerable<string>))]
public void ImplementsInterface_ReturnsFalseIfTypeDoesNotDerivesFromInterface(Type interfaceType)
{
// Arrange
var interfaceTypeInfo = new RuntimeTypeInfo(interfaceType.GetTypeInfo());
var compilation = CompilationUtility.GetCompilation("TagHelperDescriptorFactoryTagHelpers");
var tagHelperResolver = new PrecompilationTagHelperTypeResolver(compilation);
// Act
var exportedTypes = tagHelperResolver.GetExportedTypes(compilation.AssemblyName);
// Assert
var actual = Assert.Single(exportedTypes, type => type.Name == nameof(RequiredParentTagHelper));
Assert.False(actual.ImplementsInterface(interfaceTypeInfo));
}
[Fact] [Fact]
public void PropertyNamesForComplexPropertiesAreGeneratedCorrectly() public void PropertyNamesForComplexPropertiesAreGeneratedCorrectly()
{ {
@ -472,7 +527,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
// Assert // Assert
var type = Assert.Single(exportedTypes); var type = Assert.Single(exportedTypes);
Assert.False(type.IsTagHelper); Assert.False(type.ImplementsInterface(TagHelperTypeInfo));
} }
private static void AssertAttributes<TAttribute>( private static void AssertAttributes<TAttribute>(
@ -481,7 +536,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
Action<TAttribute, TAttribute> assertItem) Action<TAttribute, TAttribute> assertItem)
where TAttribute : Attribute where TAttribute : Attribute
{ {
AssertAttributes<TAttribute>(expected, actual, assertItem, attributes => attributes); AssertAttributes(expected, actual, assertItem, attributes => attributes);
} }
private static void AssertAttributes<TAttribute>( private static void AssertAttributes<TAttribute>(
@ -519,7 +574,9 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
Assert.Equal(expected.IsPublic, actual.IsPublic); Assert.Equal(expected.IsPublic, actual.IsPublic);
Assert.Equal(expected.IsAbstract, actual.IsAbstract); Assert.Equal(expected.IsAbstract, actual.IsAbstract);
Assert.Equal(expected.IsGenericType, actual.IsGenericType); Assert.Equal(expected.IsGenericType, actual.IsGenericType);
Assert.Equal(expected.IsTagHelper, actual.IsTagHelper); Assert.Equal(
expected.ImplementsInterface(TagHelperTypeInfo),
actual.ImplementsInterface(TagHelperTypeInfo));
Assert.Equal( Assert.Equal(
expected.GetGenericDictionaryParameters(), expected.GetGenericDictionaryParameters(),
actual.GetGenericDictionaryParameters(), actual.GetGenericDictionaryParameters(),

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Testing;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
@ -110,35 +111,58 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Empty(actual); Assert.Empty(actual);
} }
[Theory] [Fact]
[InlineData(typeof(ITagHelper))] public void ImplementsInterface_ThrowsIfArgumentIsNotRuntimeType()
[InlineData(typeof(TagHelper))]
[InlineData(typeof(ImplementsITagHelper))]
[InlineData(typeof(DerivesFromTagHelper))]
[InlineData(typeof(Fake.ImplementsRealITagHelper))]
public void IsTagHelper_ReturnsTrueIfTypeImplementsTagHelper(Type type)
{ {
// Arrange // Arrange
var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo()); var typeInfo = new RuntimeTypeInfo(typeof(object).GetTypeInfo());
var interfaceTypeInfo = new TestTypeInfo();
// Act and Assert
ExceptionAssert.ThrowsArgument(() => typeInfo.ImplementsInterface(interfaceTypeInfo),
"interfaceTypeInfo",
$"Argument must be an instance of '{typeof(RuntimeTypeInfo)}'.");
}
[Theory]
[InlineData(typeof(ITagHelper), typeof(ITagHelper))]
[InlineData(typeof(TagHelper), typeof(ITagHelper))]
[InlineData(typeof(ImplementsITagHelper), typeof(ITagHelper))]
[InlineData(typeof(DerivesFromTagHelper), typeof(ITagHelper))]
[InlineData(typeof(Fake.ImplementsRealITagHelper), typeof(ITagHelper))]
[InlineData(typeof(string), typeof(IEnumerable<char>))]
[InlineData(typeof(Dictionary<string, string>), typeof(IDictionary<string, string>))]
[InlineData(typeof(List<string>), typeof(IList<string>))]
[InlineData(typeof(IList<string>), typeof(IEnumerable<string>))]
public void ImplementsInterface_ReturnsTrueIfTypeImplementsInterface(Type runtimeType, Type interfaceType)
{
// Arrange
var runtimeTypeInfo = new RuntimeTypeInfo(runtimeType.GetTypeInfo());
var interfaceTypeInfo = new RuntimeTypeInfo(interfaceType.GetTypeInfo());
// Act // Act
var result = runtimeTypeInfo.IsTagHelper; var result = runtimeTypeInfo.ImplementsInterface(interfaceTypeInfo);
// Assert // Assert
Assert.True(result); Assert.True(result);
} }
[Theory] [Theory]
[InlineData(typeof(string))] [InlineData(typeof(string), typeof(object))]
[InlineData(typeof(SubType))] [InlineData(typeof(DerivesFromTagHelper), typeof(TagHelper))]
[InlineData(typeof(Fake.DoesNotImplementRealITagHelper))] [InlineData(typeof(string), typeof(ITagHelper))]
public void IsTagHelper_ReturnsFalseIfTypeDoesNotImplementTagHelper(Type type) [InlineData(typeof(string), typeof(IList<char>))]
[InlineData(typeof(SubType), typeof(ITagHelper))]
[InlineData(typeof(Fake.DoesNotImplementRealITagHelper), typeof(ITagHelper))]
[InlineData(typeof(IDictionary<,>), typeof(IDictionary<string, string>))]
public void ImplementsInterface_ReturnsTrueIfTypeDoesNotImplementInterface(Type runtimeType, Type interfaceType)
{ {
// Arrange // Arrange
var runtimeTypeInfo = new RuntimeTypeInfo(type.GetTypeInfo()); var runtimeTypeInfo = new RuntimeTypeInfo(runtimeType.GetTypeInfo());
var interfaceTypeInfo = new RuntimeTypeInfo(interfaceType.GetTypeInfo());
// Act // Act
var result = runtimeTypeInfo.IsTagHelper; var result = runtimeTypeInfo.ImplementsInterface(interfaceTypeInfo);
// Assert // Assert
Assert.False(result); Assert.False(result);
@ -502,73 +526,5 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private class CustomType private class CustomType
{ {
} }
private class TestTypeInfo : ITypeInfo
{
public string FullName { get; set; }
public bool IsAbstract
{
get
{
throw new NotImplementedException();
}
}
public bool IsGenericType
{
get
{
throw new NotImplementedException();
}
}
public bool IsPublic
{
get
{
throw new NotImplementedException();
}
}
public bool IsTagHelper
{
get
{
throw new NotImplementedException();
}
}
public string Name
{
get
{
throw new NotImplementedException();
}
}
public IEnumerable<IPropertyInfo> Properties
{
get
{
throw new NotImplementedException();
}
}
public bool Equals(ITypeInfo other)
{
throw new NotImplementedException();
}
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>() where TAttribute : Attribute
{
throw new NotImplementedException();
}
public ITypeInfo[] GetGenericDictionaryParameters()
{
throw new NotImplementedException();
}
}
} }
} }

View File

@ -0,0 +1,73 @@
// 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
{
public class TestTypeInfo : ITypeInfo
{
public string FullName { get; set; }
public bool IsAbstract
{
get
{
throw new NotImplementedException();
}
}
public bool IsGenericType
{
get
{
throw new NotImplementedException();
}
}
public bool IsPublic
{
get
{
throw new NotImplementedException();
}
}
public bool ImplementsInterface(ITypeInfo other)
{
throw new NotImplementedException();
}
public string Name
{
get
{
throw new NotImplementedException();
}
}
public IEnumerable<IPropertyInfo> Properties
{
get
{
throw new NotImplementedException();
}
}
public bool Equals(ITypeInfo other)
{
throw new NotImplementedException();
}
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>() where TAttribute : Attribute
{
throw new NotImplementedException();
}
public ITypeInfo[] GetGenericDictionaryParameters()
{
throw new NotImplementedException();
}
}
}