1010using System . Linq ;
1111using System . Reflection ;
1212using Xtensive . Core ;
13- using AttributesKey = System . ValueTuple < System . Reflection . MemberInfo , System . Type , Xtensive . Reflection . AttributeSearchOptions > ;
1413using PerAttributeKey = System . ValueTuple < System . Reflection . MemberInfo , Xtensive . Reflection . AttributeSearchOptions > ;
15- using Xtensive . Core ;
1614
1715namespace Xtensive . Reflection
1816{
@@ -21,22 +19,63 @@ namespace Xtensive.Reflection
2119 /// </summary>
2220 public static class AttributeHelper
2321 {
24- internal class AttributeExtractors < TAttribute > where TAttribute : Attribute
25- {
26- internal static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = key => {
27- var uncasted = GetAttributes ( key . Item1 , typeof ( TAttribute ) , key . Item2 ) ;
28- return uncasted . Count > 0
29- ? uncasted . Cast < TAttribute > ( ) . ToArray ( uncasted . Count )
30- : Array . Empty < TAttribute > ( ) ;
31- } ;
32- }
33-
3422 private static class AttributeDictionary < TAttribute > where TAttribute : Attribute
3523 {
24+ private static readonly Type attributeType = typeof ( TAttribute ) ;
3625 public static readonly ConcurrentDictionary < PerAttributeKey , TAttribute [ ] > Dictionary = new ( ) ;
37- }
3826
39- private static readonly ConcurrentDictionary < AttributesKey , IReadOnlyList < Attribute > > AttributesByMemberInfoAndSearchOptions = new ( ) ;
27+ private static List < TAttribute > GetAttributesAsNewList ( MemberInfo member )
28+ {
29+ var attrObjects = member . GetCustomAttributes ( attributeType , false ) ;
30+ var attrs = new List < TAttribute > ( attrObjects . Length ) ;
31+ for ( int i = 0 , count = attrObjects . Length ; i < count ; ++ i ) {
32+ attrs . Add ( ( TAttribute ) attrObjects [ i ] ) ;
33+ }
34+ return attrs ;
35+ }
36+
37+ private static void AddAttributesFromBase ( ref List < TAttribute > attributes , MemberInfo member , AttributeSearchOptions options )
38+ {
39+ if ( member . GetBaseMember ( ) is MemberInfo bm ) {
40+ var attrsToAdd = bm . GetAttributes < TAttribute > ( options ) ;
41+ if ( attrsToAdd . Count > 0 ) {
42+ ( attributes ??= new List < TAttribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
43+ }
44+ }
45+ }
46+
47+ public static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = key => {
48+ var ( member , options ) = key ;
49+
50+ var attributesAsObjects = member . GetCustomAttributes ( attributeType , false ) ;
51+ var attributesCount = attributesAsObjects . Length ;
52+
53+ var attributes = attributesCount > 0
54+ ? attributesAsObjects . Cast < TAttribute > ( ) . ToList ( attributesCount )
55+ : null ;
56+
57+ if ( options != AttributeSearchOptions . InheritNone ) {
58+ if ( attributesCount == 0 ) {
59+ if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
60+ && member is MethodInfo m
61+ && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
62+ attributes = GetAttributesAsNewList ( poe ) ;
63+ }
64+ if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
65+ && ( options & AttributeSearchOptions . InheritFromAllBase ) == 0 ) {
66+ AddAttributesFromBase ( ref attributes , member , options ) ;
67+ }
68+ }
69+
70+ if ( ( options & AttributeSearchOptions . InheritFromAllBase ) != 0
71+ && member . DeclaringType != WellKnownTypes . Object ) {
72+ AddAttributesFromBase ( ref attributes , member , options ) ;
73+ }
74+ }
75+
76+ return attributes ? . ToArray ( attributes . Count ) ?? Array . Empty < TAttribute > ( ) ;
77+ } ;
78+ }
4079
4180 /// <summary>
4281 /// A shortcut to <see cref="MemberInfo.GetCustomAttributes(Type,bool)"/> method.
@@ -48,7 +87,7 @@ private static class AttributeDictionary<TAttribute> where TAttribute : Attribut
4887 ///
4988 public static IReadOnlyList < TAttribute > GetAttributes < TAttribute > ( this MemberInfo member , AttributeSearchOptions options = AttributeSearchOptions . InheritNone )
5089 where TAttribute : Attribute =>
51- AttributeDictionary < TAttribute > . Dictionary . GetOrAdd ( new PerAttributeKey ( member , options ) , AttributeExtractors < TAttribute > . AttributesExtractor ) ;
90+ AttributeDictionary < TAttribute > . Dictionary . GetOrAdd ( new PerAttributeKey ( member , options ) , AttributeDictionary < TAttribute > . AttributesExtractor ) ;
5291
5392 /// <summary>
5493 /// A version of <see cref="GetAttributes{TAttribute}(MemberInfo, AttributeSearchOptions)"/>
@@ -74,62 +113,5 @@ public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, Attrib
74113 typeof ( TAttribute ) . GetShortName ( ) ) )
75114 } ;
76115 }
77-
78- private static IReadOnlyList < Attribute > GetAttributes ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) =>
79- AttributesByMemberInfoAndSearchOptions . GetOrAdd (
80- new AttributesKey ( member , attributeType , options ) ,
81- ExtractAttributes
82- ) ;
83-
84- private static List < Attribute > GetAttributesAsNewList ( this MemberInfo member , Type attributeType )
85- {
86- var attrObjects = member . GetCustomAttributes ( attributeType , false ) ;
87- var attrs = new List < Attribute > ( attrObjects . Length ) ;
88- for ( int i = 0 , count = attrObjects . Length ; i < count ; ++ i ) {
89- attrs . Add ( ( Attribute ) attrObjects [ i ] ) ;
90- }
91- return attrs ;
92- }
93-
94- private static IReadOnlyList < Attribute > ExtractAttributes ( ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) t )
95- {
96- ( var member , var attributeType , var options ) = t ;
97-
98- var attributesAsObjects = member . GetCustomAttributes ( attributeType , false ) ;
99- var attributesCount = attributesAsObjects . Length ;
100-
101- var attributes = attributesCount > 0
102- ? attributesAsObjects . Cast < Attribute > ( ) . ToList ( attributesCount )
103- : null ;
104-
105- if ( options != AttributeSearchOptions . InheritNone ) {
106- if ( attributesCount == 0 ) {
107- if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
108- && member is MethodInfo m
109- && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
110- attributes = poe . GetAttributesAsNewList ( attributeType ) ;
111- }
112- if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
113- && ( options & AttributeSearchOptions . InheritFromAllBase ) == 0
114- && member . GetBaseMember ( ) is MemberInfo bm ) {
115- var attrsToAdd = GetAttributes ( bm , attributeType , options ) ;
116- if ( attrsToAdd . Count > 0 ) {
117- ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
118- }
119- }
120- }
121-
122- if ( ( options & AttributeSearchOptions . InheritFromAllBase ) != 0
123- && member . DeclaringType != WellKnownTypes . Object
124- && member . GetBaseMember ( ) is MemberInfo bm2 ) {
125- var attrsToAdd = GetAttributes ( bm2 , attributeType , options ) ;
126- if ( attrsToAdd . Count > 0 ) {
127- ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
128- }
129- }
130- }
131-
132- return ( IReadOnlyList < Attribute > ) attributes ?? Array . Empty < Attribute > ( ) ;
133- }
134116 }
135117}
0 commit comments