1+ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+ using System ;
5+ using System . Collections . Generic ;
6+ using System . Linq ;
7+ using System . Reflection ;
8+ using Microsoft . AspNet . Razor . TagHelpers ;
9+
10+ namespace Microsoft . AspNet . Razor . Runtime . TagHelpers
11+ {
12+ /// <summary>
13+ /// Used to resolve <see cref="TagHelperDescriptor"/>s.
14+ /// </summary>
15+ public class TagHelperDescriptorResolver : ITagHelperDescriptorResolver
16+ {
17+ private const string TagHelperNameEnding = "TagHelper" ;
18+ private const ContentBehavior DefaultContentBehavior = default ( ContentBehavior ) ;
19+
20+ private ITagHelperTypeResolver _tagHelperTypeResolver ;
21+
22+ /// <summary>
23+ /// Instantiates a new instance of the <see cref="TagHelperDescriptorResolver"/> class.
24+ /// </summary>
25+ /// <param name="tagHelperTypeResolver">
26+ /// A type resolver used to resolve tag helper <see cref="Type"/>s.
27+ /// </param>
28+ public TagHelperDescriptorResolver ( [ NotNull ] ITagHelperTypeResolver tagHelperTypeResolver )
29+ {
30+ _tagHelperTypeResolver = tagHelperTypeResolver ;
31+ }
32+
33+ /// <summary>
34+ /// Resolves <see cref="TagHelperDescriptor"/>s based on the given <paramref name="lookupText"/>.
35+ /// </summary>
36+ /// <param name="lookupText">
37+ /// A <see cref="string"/> location on where to find tag helper <see cref="Type"/>s.
38+ /// </param>
39+ /// <returns>An <see cref="IEnumerable{TagHelperDescriptor}"/> that represent tag helpers associated with the
40+ /// given <paramref name="lookupText"/>.</returns>
41+ public IEnumerable < TagHelperDescriptor > Resolve ( string lookupText )
42+ {
43+ var tagHelperTypes = _tagHelperTypeResolver . Resolve ( lookupText ) ;
44+
45+ var descriptors = tagHelperTypes . Select ( GetTagHelperDescriptors ) ;
46+
47+ // TODO: Validate no conflicting ContentBehaviors after:
48+ // https://github.com/aspnet/Razor/issues/122 and https://github.com/aspnet/Razor/issues/120
49+
50+ return descriptors ;
51+ }
52+
53+ // TODO: Make this method return multiple TagHelperDescriptors based on a TagNameAttribute:
54+ // https://github.com/aspnet/Razor/issues/120
55+ private static TagHelperDescriptor GetTagHelperDescriptors ( Type type )
56+ {
57+ var tagName = GetTagNameTarget ( type ) ;
58+ var tagHelperTypeName = type . FullName ;
59+ var attributeDescriptors = GetTagHelperAttributeDescriptors ( type ) ;
60+ var contentBehavior = GetContentBehavior ( type ) ;
61+
62+ return new TagHelperDescriptor ( tagName ,
63+ tagHelperTypeName ,
64+ contentBehavior ,
65+ attributeDescriptors ) ;
66+ }
67+
68+ // TODO: Make this method support TagNameAttribute targets: https://github.com/aspnet/Razor/issues/120
69+ private static string GetTagNameTarget ( Type tagHelperType )
70+ {
71+ var name = tagHelperType . Name ;
72+
73+ if ( name . EndsWith ( TagHelperNameEnding , StringComparison . OrdinalIgnoreCase ) )
74+ {
75+ name = name . Substring ( 0 , name . Length - TagHelperNameEnding . Length ) ;
76+ }
77+
78+ return name ;
79+ }
80+
81+ private static IEnumerable < TagHelperAttributeDescriptor > GetTagHelperAttributeDescriptors ( Type type )
82+ {
83+ var typeInfo = type . GetTypeInfo ( ) ;
84+ var properties = typeInfo . DeclaredProperties . Where ( IsValidTagHelperProperty ) ;
85+ var attributeDescriptors = properties . Select ( ToTagHelperAttributeDescriptor ) ;
86+
87+ // TODO: Validate no conflicting HTML attribute names: https://github.com/aspnet/Razor/issues/121
88+
89+ return attributeDescriptors ;
90+ }
91+
92+ // TODO: Make the HTML attribute name support names from a AttributeNameAttribute:
93+ // https://github.com/aspnet/Razor/issues/121
94+ private static TagHelperAttributeDescriptor ToTagHelperAttributeDescriptor ( PropertyInfo property )
95+ {
96+ return new TagHelperAttributeDescriptor ( property . Name , property ) ;
97+ }
98+
99+ // TODO: Make the content behavior pull from a ContentBehaviorAttribute: https://github.com/aspnet/Razor/issues/122
100+ private static ContentBehavior GetContentBehavior ( Type type )
101+ {
102+ return DefaultContentBehavior ;
103+ }
104+
105+ private static bool IsValidTagHelperProperty ( PropertyInfo property )
106+ {
107+ return property . GetMethod != null && property . SetMethod != null ;
108+ }
109+ }
110+ }
0 commit comments